@@ -98,43 +98,36 @@ public override bool Close(BlockProcessor processor, Block block)
9898 if ( codeBlock . OpeningFencedCharCount > 3 )
9999 continue ;
100100
101- if ( span . IndexOf ( "<" ) < 0 && span . IndexOf ( "//" ) < 0 )
102- continue ;
103-
104- CallOut ? callOut = null ;
105-
106- if ( span . IndexOf ( "<" ) > 0 )
101+ List < CallOut > callOuts = [ ] ;
102+ var hasClassicCallout = span . IndexOf ( "<" ) > 0 ;
103+ if ( hasClassicCallout )
107104 {
108105 var matchClassicCallout = CallOutParser . CallOutNumber ( ) . EnumerateMatches ( span ) ;
109- callOut = EnumerateAnnotations ( matchClassicCallout , ref span , ref callOutIndex , originatingLine , false ) ;
110- }
111-
112- // only support magic callouts for smaller line lengths
113- if ( callOut is null && span . Length < 200 )
106+ callOuts . AddRange (
107+ EnumerateAnnotations ( matchClassicCallout , ref span , ref callOutIndex , originatingLine , false )
108+ ) ;
109+ } else if ( span . Length < 200 )
114110 {
115111 var matchInline = CallOutParser . MathInlineAnnotation ( ) . EnumerateMatches ( span ) ;
116- callOut = EnumerateAnnotations ( matchInline , ref span , ref callOutIndex , originatingLine ,
117- true ) ;
112+ callOuts . AddRange (
113+ EnumerateAnnotations ( matchInline , ref span , ref callOutIndex , originatingLine , true )
114+ ) ;
118115 }
119-
120- if ( callOut is null )
121- continue ;
122-
123- codeBlock . CallOuts ??= [ ] ;
124- codeBlock . CallOuts . Add ( callOut ) ;
116+ codeBlock . CallOuts . AddRange ( callOuts ) ;
125117 }
126118
127119 //update string slices to ignore call outs
128- if ( codeBlock . CallOuts is not null )
120+ if ( codeBlock . CallOuts ? . Count > 0 )
129121 {
130- foreach ( var callout in codeBlock . CallOuts )
122+ foreach ( var calloutLine in codeBlock . CallOuts . Select ( c => c . Line ) . Distinct ( ) )
131123 {
132- var line = lines . Lines [ callout . Line - 1 ] ;
133-
134- var newSpan = line . Slice . AsSpan ( ) [ ..callout . SliceStart ] ;
124+ var line = lines . Lines [ calloutLine - 1 ] ;
125+ var index = Math . Max ( line . Slice . AsSpan ( ) . IndexOf ( "//" ) , line . Slice . AsSpan ( ) . IndexOf ( '#' ) ) ;
126+ if ( index < 0 )
127+ continue ;
128+ var newSpan = line . Slice . AsSpan ( ) [ ..( index ) ] ;
135129 var s = new StringSlice ( newSpan . ToString ( ) ) ;
136- lines . Lines [ callout . Line - 1 ] = new StringLine ( ref s ) ;
137-
130+ lines . Lines [ calloutLine - 1 ] = new StringLine ( ref s ) ;
138131 }
139132 }
140133
@@ -149,44 +142,83 @@ public override bool Close(BlockProcessor processor, Block block)
149142 return base . Close ( processor , block ) ;
150143 }
151144
152- private static CallOut ? EnumerateAnnotations ( Regex . ValueMatchEnumerator matches ,
145+ private static List < CallOut > EnumerateAnnotations ( Regex . ValueMatchEnumerator matches ,
153146 ref ReadOnlySpan < char > span ,
154147 ref int callOutIndex ,
155148 int originatingLine ,
156149 bool inlineCodeAnnotation )
157150 {
151+ var callOuts = new List < CallOut > ( ) ;
158152 foreach ( var match in matches )
159153 {
160154 if ( match . Length == 0 )
161155 continue ;
162156
163- var startIndex = span . LastIndexOf ( "<" ) ;
164- if ( ! inlineCodeAnnotation && startIndex <= 0 )
165- continue ;
166157 if ( inlineCodeAnnotation )
167158 {
168- startIndex = Math . Max ( span . LastIndexOf ( "//" ) , span . LastIndexOf ( '#' ) ) ;
169- if ( startIndex <= 0 )
170- continue ;
159+ var callOut = ParseMagicCallout ( match , ref span , ref callOutIndex , originatingLine ) ;
160+ if ( callOut != null )
161+ return [ callOut ] ;
162+ continue ;
171163 }
172164
173- callOutIndex ++ ;
174- var callout = span . Slice ( match . Index + startIndex , match . Length - startIndex ) ;
175- var index = callOutIndex ;
176- if ( ! inlineCodeAnnotation && int . TryParse ( callout . Trim ( [ '<' , '>' ] ) , out index ) )
177- {
165+ var classicCallOuts = ParseClassicCallOuts ( match , ref span , ref callOutIndex , originatingLine ) ;
166+ callOuts . AddRange ( classicCallOuts ) ;
167+ }
178168
179- }
180- return new CallOut
169+ return callOuts ;
170+ }
171+
172+ private static CallOut ? ParseMagicCallout ( ValueMatch match , ref ReadOnlySpan < char > span , ref int callOutIndex , int originatingLine )
173+ {
174+ var startIndex = Math . Max ( span . LastIndexOf ( "//" ) , span . LastIndexOf ( '#' ) ) ;
175+ if ( startIndex <= 0 )
176+ return null ;
177+
178+ callOutIndex ++ ;
179+ var callout = span . Slice ( match . Index + startIndex , match . Length - startIndex ) ;
180+
181+ return new CallOut
182+ {
183+ Index = callOutIndex ,
184+ Text = callout . TrimStart ( '/' ) . TrimStart ( '#' ) . TrimStart ( ) . ToString ( ) ,
185+ InlineCodeAnnotation = true ,
186+ SliceStart = startIndex ,
187+ Line = originatingLine ,
188+ } ;
189+ }
190+
191+ private static List < CallOut > ParseClassicCallOuts ( ValueMatch match , ref ReadOnlySpan < char > span , ref int callOutIndex , int originatingLine )
192+ {
193+ var startIndex = span . LastIndexOf ( "<" ) ;
194+ if ( startIndex <= 0 )
195+ return [ ] ;
196+
197+ callOutIndex ++ ;
198+
199+ var allStartIndices = new List < int > ( ) ;
200+ for ( var i = 0 ; i < span . Length ; i ++ )
201+ {
202+ if ( span [ i ] == '<' )
203+ allStartIndices . Add ( i ) ;
204+ }
205+
206+ var callOuts = new List < CallOut > ( ) ;
207+ foreach ( var individualStartIndex in allStartIndices )
208+ {
209+ var endIndex = span . Slice ( match . Index + individualStartIndex ) . IndexOf ( '>' ) + 1 ;
210+ var callout = span . Slice ( match . Index + individualStartIndex , endIndex ) ;
211+ _ = int . TryParse ( callout . Trim ( [ '<' , '>' ] ) , out var index ) ;
212+ callOuts . Add ( new CallOut
181213 {
182214 Index = index ,
183215 Text = callout . TrimStart ( '/' ) . TrimStart ( '#' ) . TrimStart ( ) . ToString ( ) ,
184- InlineCodeAnnotation = inlineCodeAnnotation ,
185- SliceStart = startIndex ,
216+ InlineCodeAnnotation = false ,
217+ SliceStart = individualStartIndex ,
186218 Line = originatingLine ,
187- } ;
219+ } ) ;
188220 }
189221
190- return null ;
222+ return callOuts ;
191223 }
192224}
0 commit comments