Houshan-Basa/lib/ui/widgets/components/text/latex.dart

98 lines
3.1 KiB
Dart

// 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<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.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,
));
}
}