77import org .commonmark .parser .InlineParser ;
88import org .commonmark .parser .InlineParserContext ;
99import org .commonmark .parser .SourceLines ;
10- import org .commonmark .parser .beta .Position ;
10+ import org .commonmark .parser .beta .* ;
1111import org .commonmark .parser .beta .Scanner ;
1212import org .commonmark .parser .delimiter .DelimiterProcessor ;
1313import org .commonmark .text .Characters ;
1616
1717public class InlineParserImpl implements InlineParser , InlineParserState {
1818
19- private final BitSet specialCharacters ;
20- private final Map <Character , DelimiterProcessor > delimiterProcessors ;
2119 private final InlineParserContext context ;
22- private final Map <Character , List <InlineContentParser >> inlineParsers ;
20+ private final List <InlineContentParserFactory > inlineContentParserFactories ;
21+ private final Map <Character , DelimiterProcessor > delimiterProcessors ;
22+ private final BitSet specialCharacters ;
2323
24+ private Map <Character , List <InlineContentParser >> inlineParsers ;
2425 private Scanner scanner ;
2526 private boolean includeSourceSpans ;
2627 private int trailingSpaces ;
@@ -36,46 +37,31 @@ public class InlineParserImpl implements InlineParser, InlineParserState {
3637 */
3738 private Bracket lastBracket ;
3839
39- public InlineParserImpl (InlineParserContext inlineParserContext ) {
40- this .delimiterProcessors = calculateDelimiterProcessors (inlineParserContext .getCustomDelimiterProcessors ());
41-
42- this .context = inlineParserContext ;
43- this .inlineParsers = new HashMap <>();
44- this .inlineParsers .put ('\\' , Collections .<InlineContentParser >singletonList (new BackslashInlineParser ()));
45- this .inlineParsers .put ('`' , Collections .<InlineContentParser >singletonList (new BackticksInlineParser ()));
46- this .inlineParsers .put ('&' , Collections .<InlineContentParser >singletonList (new EntityInlineParser ()));
47- this .inlineParsers .put ('<' , Arrays .asList (new AutolinkInlineParser (), new HtmlInlineParser ()));
48-
49- this .specialCharacters = calculateSpecialCharacters (this .delimiterProcessors .keySet (), inlineParsers .keySet ());
40+ public InlineParserImpl (InlineParserContext context ) {
41+ this .context = context ;
42+ this .inlineContentParserFactories = calculateInlineContentParserFactories (context .getCustomInlineContentParserFactories ());
43+ this .delimiterProcessors = calculateDelimiterProcessors (context .getCustomDelimiterProcessors ());
44+ this .specialCharacters = calculateSpecialCharacters (this .delimiterProcessors .keySet (), this .inlineContentParserFactories );
5045 }
5146
52- public static BitSet calculateSpecialCharacters (Set <Character > delimiterCharacters , Set <Character > characters ) {
53- BitSet bitSet = new BitSet ();
54- for (Character c : delimiterCharacters ) {
55- bitSet .set (c );
56- }
57- for (Character c : characters ) {
58- bitSet .set (c );
59- }
60- bitSet .set ('[' );
61- bitSet .set (']' );
62- bitSet .set ('!' );
63- bitSet .set ('\n' );
64- return bitSet ;
47+ private List <InlineContentParserFactory > calculateInlineContentParserFactories (List <InlineContentParserFactory > customFactories ) {
48+ // Custom parsers can override built-in parsers if they want, so make sure they are tried first
49+ var list = new ArrayList <>(customFactories );
50+ list .add (new BackslashInlineParser .Factory ());
51+ list .add (new BackticksInlineParser .Factory ());
52+ list .add (new EntityInlineParser .Factory ());
53+ list .add (new AutolinkInlineParser .Factory ());
54+ list .add (new HtmlInlineParser .Factory ());
55+ return list ;
6556 }
6657
67- public static Map <Character , DelimiterProcessor > calculateDelimiterProcessors (List <DelimiterProcessor > delimiterProcessors ) {
68- Map < Character , DelimiterProcessor > map = new HashMap <>();
69- addDelimiterProcessors (Arrays .< DelimiterProcessor > asList (new AsteriskDelimiterProcessor (), new UnderscoreDelimiterProcessor ()), map );
58+ private static Map <Character , DelimiterProcessor > calculateDelimiterProcessors (List <DelimiterProcessor > delimiterProcessors ) {
59+ var map = new HashMap <Character , DelimiterProcessor >();
60+ addDelimiterProcessors (List . of (new AsteriskDelimiterProcessor (), new UnderscoreDelimiterProcessor ()), map );
7061 addDelimiterProcessors (delimiterProcessors , map );
7162 return map ;
7263 }
7364
74- @ Override
75- public Scanner scanner () {
76- return scanner ;
77- }
78-
7965 private static void addDelimiterProcessors (Iterable <DelimiterProcessor > delimiterProcessors , Map <Character , DelimiterProcessor > map ) {
8066 for (DelimiterProcessor delimiterProcessor : delimiterProcessors ) {
8167 char opening = delimiterProcessor .getOpeningCharacter ();
@@ -109,6 +95,40 @@ private static void addDelimiterProcessorForChar(char delimiterChar, DelimiterPr
10995 }
11096 }
11197
98+ private static BitSet calculateSpecialCharacters (Set <Character > delimiterCharacters ,
99+ List <InlineContentParserFactory > inlineContentParserFactories ) {
100+ BitSet bitSet = new BitSet ();
101+ for (Character c : delimiterCharacters ) {
102+ bitSet .set (c );
103+ }
104+ for (var factory : inlineContentParserFactories ) {
105+ for (var c : factory .getTriggerCharacters ()) {
106+ bitSet .set (c );
107+ }
108+ }
109+ bitSet .set ('[' );
110+ bitSet .set (']' );
111+ bitSet .set ('!' );
112+ bitSet .set ('\n' );
113+ return bitSet ;
114+ }
115+
116+ private Map <Character , List <InlineContentParser >> createInlineContentParsers () {
117+ var map = new HashMap <Character , List <InlineContentParser >>();
118+ for (var factory : inlineContentParserFactories ) {
119+ var parser = factory .create ();
120+ for (var c : factory .getTriggerCharacters ()) {
121+ map .computeIfAbsent (c , k -> new ArrayList <>()).add (parser );
122+ }
123+ }
124+ return map ;
125+ }
126+
127+ @ Override
128+ public Scanner scanner () {
129+ return scanner ;
130+ }
131+
112132 /**
113133 * Parse content in block into inline children, appending them to the block node.
114134 */
@@ -117,14 +137,13 @@ public void parse(SourceLines lines, Node block) {
117137 reset (lines );
118138
119139 while (true ) {
120- List <? extends Node > nodes = parseInline ();
121- if (nodes != null ) {
122- for (Node node : nodes ) {
123- block .appendChild (node );
124- }
125- } else {
140+ var nodes = parseInline ();
141+ if (nodes == null ) {
126142 break ;
127143 }
144+ for (Node node : nodes ) {
145+ block .appendChild (node );
146+ }
128147 }
129148
130149 processDelimiters (null );
@@ -137,6 +156,7 @@ void reset(SourceLines lines) {
137156 this .trailingSpaces = 0 ;
138157 this .lastDelimiter = null ;
139158 this .lastBracket = null ;
159+ this .inlineParsers = createInlineContentParsers ();
140160 }
141161
142162 private Text text (SourceLines sourceLines ) {
@@ -155,20 +175,20 @@ private List<? extends Node> parseInline() {
155175
156176 switch (c ) {
157177 case '[' :
158- return Collections . singletonList (parseOpenBracket ());
178+ return List . of (parseOpenBracket ());
159179 case '!' :
160- return Collections . singletonList (parseBang ());
180+ return List . of (parseBang ());
161181 case ']' :
162- return Collections . singletonList (parseCloseBracket ());
182+ return List . of (parseCloseBracket ());
163183 case '\n' :
164- return Collections . singletonList (parseLineBreak ());
184+ return List . of (parseLineBreak ());
165185 case Scanner .END :
166186 return null ;
167187 }
168188
169189 // No inline parser, delimiter or other special handling.
170190 if (!specialCharacters .get (c )) {
171- return Collections . singletonList (parseText ());
191+ return List . of (parseText ());
172192 }
173193
174194 List <InlineContentParser > inlineParsers = this .inlineParsers .get (c );
@@ -183,7 +203,7 @@ private List<? extends Node> parseInline() {
183203 if (includeSourceSpans && node .getSourceSpans ().isEmpty ()) {
184204 node .setSourceSpans (scanner .getSource (position , scanner .position ()).getSourceSpans ());
185205 }
186- return Collections . singletonList (node );
206+ return List . of (node );
187207 } else {
188208 // Reset position
189209 scanner .setPosition (position );
@@ -200,7 +220,7 @@ private List<? extends Node> parseInline() {
200220 }
201221
202222 // If we get here, even for a special/delimiter character, we will just treat it as text.
203- return Collections . singletonList (parseText ());
223+ return List . of (parseText ());
204224 }
205225
206226 /**
0 commit comments