diff --git a/example/pubspec.lock b/example/pubspec.lock index f8a6b42..0af4d7a 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -66,25 +66,25 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "4.0.0" flutter_markdown: dependency: "direct main" description: name: flutter_markdown - sha256: "04c4722cc36ec5af38acc38ece70d22d3c2123c61305d555750a091517bbe504" + sha256: a23c41ee57573e62fc2190a1f36a0480c4d90bde3a8a8d7126e5d5992fb53fb7 url: "https://pub.dev" source: hosted - version: "0.6.23" + version: "0.7.3+1" flutter_markdown_latex: dependency: "direct main" description: path: ".." relative: true source: path - version: "0.3.2" + version: "0.3.3" flutter_math_fork: dependency: "direct main" description: @@ -110,10 +110,10 @@ packages: dependency: transitive description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_parser: dependency: transitive description: @@ -126,34 +126,34 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.4" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.3" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: name: lints - sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "4.0.0" markdown: dependency: "direct main" description: @@ -182,10 +182,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" nested: dependency: transitive description: @@ -275,10 +275,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" tuple: dependency: transitive description: @@ -331,18 +331,18 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.1" web: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.0.0" xml: dependency: transitive description: @@ -352,5 +352,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.3.0 <4.0.0" + dart: ">=3.4.0 <4.0.0" flutter: ">=3.19.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 48b826e..6aec2e0 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -35,7 +35,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - flutter_markdown: ^0.6.18+3 + flutter_markdown: ^0.7.3+1 markdown: ^7.1.1 flutter_math_fork: ^0.7.2 @@ -48,7 +48,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^3.0.1 + flutter_lints: ^4.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/lib/src/latex_block_syntax.dart b/lib/src/latex_block_syntax.dart index 70edd6b..d99e3da 100644 --- a/lib/src/latex_block_syntax.dart +++ b/lib/src/latex_block_syntax.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:markdown/markdown.dart'; class LatexBlockSyntax extends BlockSyntax { @@ -40,7 +38,6 @@ class LatexBlockSyntax extends BlockSyntax { Node parse(BlockParser parser) { final lines = parseChildLines(parser); final content = lines.map((e) => e.content).join('\n').trim(); - log('content: $content'); final textElement = Element.text('latex', content); textElement.attributes['MathStyle'] = 'display'; diff --git a/lib/src/latex_inline_syntax.dart b/lib/src/latex_inline_syntax.dart index b604a38..3b8f0d4 100644 --- a/lib/src/latex_inline_syntax.dart +++ b/lib/src/latex_inline_syntax.dart @@ -1,31 +1,67 @@ import 'package:markdown/markdown.dart'; -const _latexPattern = - r'(?:(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n\$]))\1(?=[\s?!\.,:?!。,:]|$))|(?:(\\\()(?!\\\))((?:\\.|[^\\\n])*?)\\\)(?=[\s?!\.,:?!。,:]|$))'; +final List> delimiterList = [ + {'left': r'$$', 'right': r'$$', 'display': true}, + {'left': r'$', 'right': r'$', 'display': false}, + {'left': r'\pu{', 'right': '}', 'display': false}, + {'left': r'\ce{', 'right': '}', 'display': false}, + {'left': r'\(', 'right': r'\)', 'display': false}, + {'left': '( ', 'right': ' )', 'display': false}, + {'left': r'\[', 'right': r'\]', 'display': true}, + {'left': '[ ', 'right': ' ]', 'display': true}, +]; + +List inlinePatterns = []; +List blockPatterns = []; + +String escapeRegex(String string) { + return string.replaceAllMapped(RegExp(r'[-\/\\^$*+?.()|[\]{}]'), (match) { + return '\\${match.group(0)}'; + }); +} + +String generateRegexRules(List> delimiters) { + for (var delimiter in delimiters) { + String left = delimiter['left']; + String right = delimiter['right']; + // Ensure regex-safe delimiters + String escapedLeft = escapeRegex(left); + String escapedRight = escapeRegex(right); + + // Inline pattern + inlinePatterns.add( + '$escapedLeft((?:\\\\.|[^\\\\\\n])*?(?:\\\\.|[^\\\\\\n]|(?!$escapedRight)))$escapedRight'); + // Block pattern + blockPatterns.add('$escapedLeft\\n((?:\\\\[^]|[^\\\\])+?)\\n$escapedRight'); + } + + return '(${inlinePatterns.join("|")})(?=[\\s?!.,:?!。,:]|\$)'; +} + +final _latexPattern = generateRegexRules(delimiterList); class LatexInlineSyntax extends InlineSyntax { LatexInlineSyntax() : super(_latexPattern); @override bool onMatch(InlineParser parser, Match match) { - if (match.groupCount < 3) { - return false; - } - - String equation = (match[2] ?? '').trim(); - if (equation.isEmpty) { - equation = (match[4] ?? '').trim(); - } - String raw = match.group(0) ?? ''; - String mathStyle; - if (raw.startsWith('\$\$') && raw.endsWith('\$\$')) { - mathStyle = 'display'; - } else { - mathStyle = 'text'; + int delimiterLength = 1; + String mathStyle = 'text'; + // check delimiter + for (var delimiter in delimiterList) { + if (raw.startsWith(delimiter['left']) && + raw.endsWith(delimiter['right'])) { + mathStyle = delimiter['display'] ? 'display' : 'text'; + delimiterLength = delimiter['left'].length; + break; + } } + final equation = + raw.substring(delimiterLength, raw.length - delimiterLength); + final element = Element.text('latex', equation); element.attributes['MathStyle'] = mathStyle; parser.addNode(element);