Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:markdown_editor/device_preference_notifier.dart';
import 'package:markdown_editor/l10n/generated/app_localizations.dart';
import 'package:markdown_editor/widgets/MarkdownBody/custom_image_config.dart';
import 'package:markdown_editor/widgets/MarkdownBody/custom_text_node.dart';
import 'package:markdown_editor/widgets/MarkdownBody/latex_node.dart';
import 'package:markdown_editor/widgets/MarkdownTextInput/markdown_text_input.dart';
import 'package:markdown_widget/markdown_widget.dart';

Expand Down Expand Up @@ -228,6 +229,8 @@ class _HomeState extends State<Home> {
child: MarkdownBlock(
data: _inputText,
generator: MarkdownGenerator(
generators: [latexGenerator],
inlineSyntaxList: [LatexSyntax()],
textGenerator: (node, config, visitor) =>
CustomTextNode(node.textContent, config, visitor),
richTextBuilder: Text.rich,
Expand Down
77 changes: 77 additions & 0 deletions lib/widgets/MarkdownBody/latex_node.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import 'package:flutter/material.dart';
import 'package:flutter_math_fork/flutter_math.dart';
import 'package:markdown/markdown.dart' as m;
import 'package:markdown_widget/markdown_widget.dart';

SpanNodeGeneratorWithTag latexGenerator = SpanNodeGeneratorWithTag(
tag: _latexTag,
generator: (e, config, visitor) =>
LatexNode(e.attributes, e.textContent, config),
);

const _latexTag = 'latex';

class LatexSyntax extends m.InlineSyntax {
LatexSyntax() : super(r'(\$\$[\s\S]+\$\$)|(\$.+?\$)');

@override
bool onMatch(m.InlineParser parser, Match match) {
final input = match.input;
final matchValue = input.substring(match.start, match.end);
String content = '';
bool isInline = true;
const blockSyntax = '\$\$';
const inlineSyntax = '\$';
if (matchValue.startsWith(blockSyntax) &&
matchValue.endsWith(blockSyntax) &&
(matchValue != blockSyntax)) {
content = matchValue.substring(2, matchValue.length - 2);
isInline = false;
} else if (matchValue.startsWith(inlineSyntax) &&
matchValue.endsWith(inlineSyntax) &&
matchValue != inlineSyntax) {
content = matchValue.substring(1, matchValue.length - 1);
}
final m.Element el = m.Element.text(_latexTag, matchValue);
el.attributes['content'] = content;
el.attributes['isInline'] = '$isInline';
parser.addNode(el);
return true;
}
}

class LatexNode extends SpanNode {
final Map<String, String> attributes;
final String textContent;
final MarkdownConfig config;

LatexNode(this.attributes, this.textContent, this.config);

@override
InlineSpan build() {
final content = attributes['content'] ?? '';
final isInline = attributes['isInline'] == 'true';
final style = parentStyle ?? config.p.textStyle;
if (content.isEmpty) return TextSpan(style: style, text: textContent);

final latex = Math.tex(
content,
mathStyle: MathStyle.text,
textStyle: style,
textScaleFactor: 1,
onErrorFallback: (error) {
return Text(textContent, style: style.copyWith(color: Colors.red));
},
);
return WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: !isInline
? Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(vertical: 16),
child: Center(child: latex),
)
: latex,
);
}
}
32 changes: 32 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_math_fork:
dependency: "direct main"
description:
name: flutter_math_fork
sha256: "6d5f2f1aa57ae539ffb0a04bb39d2da67af74601d685a161aff7ce5bda5fa407"
url: "https://pub.dev"
source: hosted
version: "0.7.4"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
Expand Down Expand Up @@ -293,6 +301,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.16.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
path:
dependency: transitive
description:
Expand Down Expand Up @@ -405,6 +421,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.8"
provider:
dependency: transitive
description:
name: provider
sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
url: "https://pub.dev"
source: hosted
version: "6.1.5+1"
scroll_to_index:
dependency: transitive
description:
Expand Down Expand Up @@ -522,6 +546,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.6"
tuple:
dependency: transitive
description:
name: tuple
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
url: "https://pub.dev"
source: hosted
version: "2.0.2"
typed_data:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies:
sdk: flutter
flutter_localizations:
sdk: flutter
flutter_math_fork: ^0.7.4
flutter_svg: ^2.2.1
flutter_widget_from_html_core: ^0.17.0
html: ^0.15.6
Expand Down