@@ -5,40 +5,48 @@ import 'package:super_editor_markdown/super_editor_markdown.dart';
55
66/// Parses inline markdown content.
77///
8- /// Supports strikethrough, underline, bold, italics, code and links.
8+ /// {@macro markdown_two_phase}
99///
10- /// The given [syntax] controls how the [text] is parsed, e.g., [MarkdownSyntax.normal]
11- /// for strict Markdown parsing, or [MarkdownSyntax.superEditor] to use Super Editor's
12- /// extended syntax.
10+ /// {@macro inline_markdown_syntaxes}
1311///
1412/// If [encodeHtml] is `true` , it escapes HTML symbols like &, <, and >. For example,
1513/// `&` becomes `&` , `<` becomes `<` , and `>` becomes `>` .
1614AttributedText parseInlineMarkdown (
1715 String text, {
18- MarkdownSyntax syntax = MarkdownSyntax .superEditor,
16+ Iterable <md.InlineSyntax >? inlineMarkdownSyntaxes,
17+ Iterable <InlineHtmlSyntax >? inlineHtmlSyntaxes,
1918 bool encodeHtml = false ,
2019}) {
2120 final inlineParser = md.InlineParser (
2221 text,
2322 md.Document (
24- inlineSyntaxes: [
25- SingleStrikethroughSyntax (), // this needs to be before md.StrikethroughSyntax to be recognized
26- md.StrikethroughSyntax (),
27- UnderlineSyntax (),
28- if (syntax == MarkdownSyntax .superEditor) //
29- SuperEditorImageSyntax (),
30- ],
23+ inlineSyntaxes: inlineMarkdownSyntaxes ?? defaultSuperEditorInlineSyntaxes,
3124 encodeHtml: encodeHtml,
3225 ),
3326 );
34- final inlineVisitor = _InlineMarkdownToDocument ();
27+ final inlineVisitor = _InlineMarkdownToDocument (
28+ inlineHtmlSyntaxes: inlineHtmlSyntaxes ?? defaultInlineHtmlSyntaxes,
29+ );
3530 final inlineNodes = inlineParser.parse ();
3631 for (final inlineNode in inlineNodes) {
3732 inlineNode.accept (inlineVisitor);
3833 }
3934 return inlineVisitor.attributedText;
4035}
4136
37+ final defaultSuperEditorInlineSyntaxes = [
38+ SingleStrikethroughSyntax (), // this needs to be before md.StrikethroughSyntax to be recognized
39+ md.StrikethroughSyntax (),
40+ UnderlineSyntax (),
41+ SuperEditorImageSyntax (),
42+ ];
43+
44+ final defaultNonSuperEditorInlineSyntaxes = [
45+ SingleStrikethroughSyntax (), // this needs to be before md.StrikethroughSyntax to be recognized
46+ md.StrikethroughSyntax (),
47+ UnderlineSyntax (),
48+ ];
49+
4250/// Parses inline markdown content.
4351///
4452/// Apply [_InlineMarkdownToDocument] to a text [md.Element] to
@@ -49,7 +57,11 @@ AttributedText parseInlineMarkdown(
4957/// that contains image tags. If any non-image text is found,
5058/// the content is treated as styled text.
5159class _InlineMarkdownToDocument implements md.NodeVisitor {
52- _InlineMarkdownToDocument ();
60+ _InlineMarkdownToDocument ({
61+ required this .inlineHtmlSyntaxes,
62+ });
63+
64+ final Iterable <InlineHtmlSyntax > inlineHtmlSyntaxes;
5365
5466 AttributedText get attributedText => _textStack.first;
5567
@@ -72,38 +84,14 @@ class _InlineMarkdownToDocument implements md.NodeVisitor {
7284 void visitElementAfter (md.Element element) {
7385 // Reset to normal text style because a plain text element does
7486 // not receive a call to visitElementBefore().
75- final styledText = _textStack.removeLast ();
76-
77- if (element.tag == 'strong' ) {
78- styledText.addAttribution (
79- boldAttribution,
80- SpanRange (0 , styledText.length - 1 ),
81- );
82- } else if (element.tag == 'em' ) {
83- styledText.addAttribution (
84- italicsAttribution,
85- SpanRange (0 , styledText.length - 1 ),
86- );
87- } else if (element.tag == "del" ) {
88- styledText.addAttribution (
89- strikethroughAttribution,
90- SpanRange (0 , styledText.length - 1 ),
91- );
92- } else if (element.tag == "code" ) {
93- styledText.addAttribution (
94- codeAttribution,
95- SpanRange (0 , styledText.length - 1 ),
96- );
97- } else if (element.tag == "u" ) {
98- styledText.addAttribution (
99- underlineAttribution,
100- SpanRange (0 , styledText.length - 1 ),
101- );
102- } else if (element.tag == 'a' ) {
103- styledText.addAttribution (
104- LinkAttribution .fromUri (Uri .parse (element.attributes['href' ]! )),
105- SpanRange (0 , styledText.length - 1 ),
106- );
87+ var styledText = _textStack.removeLast ();
88+
89+ for (final inlineHtmlSyntax in inlineHtmlSyntaxes) {
90+ final finalText = inlineHtmlSyntax (element, styledText);
91+ if (finalText != null ) {
92+ styledText = finalText;
93+ break ;
94+ }
10795 }
10896
10997 if (_textStack.isNotEmpty) {
@@ -114,3 +102,86 @@ class _InlineMarkdownToDocument implements md.NodeVisitor {
114102 }
115103 }
116104}
105+
106+ const defaultInlineHtmlSyntaxes = [
107+ boldHtmlSyntax,
108+ italicHtmlSyntax,
109+ underlineHtmlSyntax,
110+ strikethroughHtmlSyntax,
111+ anchorHtmlSyntax,
112+ codeInlineHtmlSyntax,
113+ ];
114+
115+ typedef InlineHtmlSyntax = AttributedText ? Function (md.Element element, AttributedText text);
116+
117+ AttributedText ? boldHtmlSyntax (md.Element element, AttributedText text) {
118+ if (element.tag != 'strong' ) {
119+ return null ;
120+ }
121+
122+ return text
123+ ..addAttribution (
124+ boldAttribution,
125+ SpanRange (0 , text.length - 1 ),
126+ );
127+ }
128+
129+ AttributedText ? italicHtmlSyntax (md.Element element, AttributedText text) {
130+ if (element.tag != 'em' ) {
131+ return null ;
132+ }
133+
134+ return text
135+ ..addAttribution (
136+ italicsAttribution,
137+ SpanRange (0 , text.length - 1 ),
138+ );
139+ }
140+
141+ AttributedText ? underlineHtmlSyntax (md.Element element, AttributedText text) {
142+ if (element.tag != 'u' ) {
143+ return null ;
144+ }
145+
146+ return text
147+ ..addAttribution (
148+ underlineAttribution,
149+ SpanRange (0 , text.length - 1 ),
150+ );
151+ }
152+
153+ AttributedText ? strikethroughHtmlSyntax (md.Element element, AttributedText text) {
154+ if (element.tag != 'del' ) {
155+ return null ;
156+ }
157+
158+ return text
159+ ..addAttribution (
160+ strikethroughAttribution,
161+ SpanRange (0 , text.length - 1 ),
162+ );
163+ }
164+
165+ AttributedText ? anchorHtmlSyntax (md.Element element, AttributedText text) {
166+ if (element.tag != 'a' ) {
167+ return null ;
168+ }
169+
170+ return text
171+ ..addAttribution (
172+ LinkAttribution .fromUri (Uri .parse (element.attributes['href' ]! )),
173+ SpanRange (0 , text.length - 1 ),
174+ );
175+ }
176+
177+ AttributedText ? codeInlineHtmlSyntax (md.Element element, AttributedText text) {
178+ if (element.tag != 'code' ) {
179+ return null ;
180+ }
181+
182+ return text
183+ ..addAttribution (
184+ codeAttribution,
185+ SpanRange (0 , text.length - 1 ),
186+ );
187+ }
0 commit comments