From 44ae74800d2b7e7993cf309c7d1595e296e69f6f Mon Sep 17 00:00:00 2001 From: peron Date: Wed, 13 Dec 2023 15:28:39 +0000 Subject: [PATCH] feat: support rendering latex --- lib/utils/latex.dart | 25 +++++++++++ lib/utils/string.dart | 15 +++++++ lib/widgets/message_tile.dart | 11 ++++- pubspec.lock | 80 +++++++++++++++++++++++++++++++++++ pubspec.yaml | 1 + 5 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 lib/utils/latex.dart create mode 100644 lib/utils/string.dart diff --git a/lib/utils/latex.dart b/lib/utils/latex.dart new file mode 100644 index 0000000..3245df7 --- /dev/null +++ b/lib/utils/latex.dart @@ -0,0 +1,25 @@ +import 'package:flutter_markdown_latex/flutter_markdown_latex.dart'; +import 'package:markdown/markdown.dart'; + +class BingLatexBlockSyntax extends LatexBlockSyntax { + @override + List parseChildLines(BlockParser parser) { + final childLines = super.parseChildLines(parser); + + return [Line("\\begin{aligned}"), ...childLines, Line("\\end{aligned}")]; + } +} + +class BingLatexInlineSyntax extends InlineSyntax { + BingLatexInlineSyntax() + : super(r'(\\\()(?![\n])(.*?)(\\\))(?=[\s?!\.,:?!。,:]|$)'); + + @override + bool onMatch(InlineParser parser, Match match) { + Element element = Element.text('latex', match[2] ?? ''); + element.attributes['displayMode'] = + match[1]?.length == 2 ? 'true' : 'false'; + parser.addNode(element); + return true; + } +} diff --git a/lib/utils/string.dart b/lib/utils/string.dart new file mode 100644 index 0000000..4e814a1 --- /dev/null +++ b/lib/utils/string.dart @@ -0,0 +1,15 @@ +extension SuffixOperation on String { + String removeSuffix(String suffix) { + if (endsWith(suffix)) { + return substring(0, length - suffix.length); + } + return this; + } + + String replaceSuffix(String suffix, String replacement) { + if (endsWith(suffix)) { + return substring(0, length - suffix.length) + replacement; + } + return this; + } +} diff --git a/lib/widgets/message_tile.dart b/lib/widgets/message_tile.dart index d0c952b..92d7d82 100644 --- a/lib/widgets/message_tile.dart +++ b/lib/widgets/message_tile.dart @@ -6,8 +6,10 @@ import 'package:get/get.dart'; import 'package:markdown/markdown.dart' as md; import 'package:sydney_webui/controller.dart'; import 'package:sydney_webui/models/message.dart'; +import 'package:sydney_webui/utils/latex.dart'; import 'package:sydney_webui/utils/url.dart'; import 'package:sydney_webui/widgets/code_element.dart'; +import 'package:flutter_markdown_latex/flutter_markdown_latex.dart'; class MessageTile extends StatelessWidget { const MessageTile({ @@ -140,9 +142,16 @@ class MessageTile extends StatelessWidget { md.MarkdownBody( selectable: true, data: message.content, - extensionSet: md.ExtensionSet.gitHubFlavored, + extensionSet: md.ExtensionSet([ + ...md.ExtensionSet.gitHubFlavored.blockSyntaxes, + BingLatexBlockSyntax() + ], [ + ...md.ExtensionSet.gitHubFlavored.inlineSyntaxes, + BingLatexInlineSyntax() + ]), builders: { 'code': CodeElementBuilder(), + 'latex': LatexElementBuilder(), }), ...typeSpecificContent, ...images diff --git a/pubspec.lock b/pubspec.lock index ef990d0..2367860 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -126,6 +126,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.18+2" + flutter_markdown_latex: + dependency: "direct main" + description: + name: flutter_markdown_latex + sha256: fff914d779c9b30b8b261b4c087bb08b3962ac024e4c6a0a5613b5c12c17725a + url: "https://pub.dev" + source: hosted + version: "0.1.3" + flutter_math_fork: + dependency: transitive + description: + name: flutter_math_fork + sha256: "94bee4642892a94939af0748c6a7de0ff8318feee588379dcdfea7dc5cba06c8" + url: "https://pub.dev" + source: hosted + version: "0.7.2" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -134,6 +150,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.17" + flutter_svg: + dependency: transitive + description: + name: flutter_svg + sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + url: "https://pub.dev" + source: hosted + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -248,6 +272,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" pasteboard: dependency: "direct main" description: @@ -264,6 +296,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_provider: dependency: transitive description: @@ -344,6 +384,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.7.3" + provider: + dependency: transitive + description: + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + url: "https://pub.dev" + source: hosted + version: "6.1.1" sky_engine: dependency: transitive description: flutter @@ -397,6 +445,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" typed_data: dependency: transitive description: @@ -405,6 +461,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26 + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c364ba9..00620a8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: flutter_highlighter: pasteboard: image: + flutter_markdown_latex: dev_dependencies: flutter_test: