// ignore_for_file: depend_on_referenced_packages import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:markdown_widget/markdown_widget.dart'; import 'package:flutter_math_fork/flutter_math.dart'; import 'package:markdown/markdown.dart' as m; 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); } 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 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.code.style; if (content.isEmpty) return TextSpan(style: style, text: textContent); final latex = Math.tex( content, mathStyle: MathStyle.text, textScaleFactor: 1, textStyle: config.code.style.copyWith( fontSize: 14, fontWeight: FontWeight.bold, ), onErrorFallback: (error) { if (kDebugMode) { print("Error is: $error"); } return Text( textContent, style: style, ); }, ); return WidgetSpan( alignment: PlaceholderAlignment.middle, style: style, child: Directionality( textDirection: TextDirection.ltr, // Change text direction here child: !isInline ? Container( width: double.infinity, margin: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: config.code.style.backgroundColor, borderRadius: BorderRadius.circular(10)), padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 24), child: Center(child: Flexible(child: latex)), ) : latex, )); } }