@@ -22,6 +22,8 @@ public class WikiEngineState
2222 public ITwSharedLocalizationText Localizer { get ; private set ; }
2323
2424 private int _matchesStoredPerIteration = 0 ;
25+ private int _stepNumber = 0 ;
26+ private HashSet < string > _storeAllMatchCache = new ( ) ;
2527
2628 /// <summary>
2729 /// The HTML tag name used to identify anything that needs a name.
@@ -64,59 +66,6 @@ public class WikiEngineState
6466
6567 #endregion
6668
67- private int _stepNumber = 0 ;
68- /// <summary>
69- /// Gets the next string to use for generating unique tag identifiers during processing, incrementing the internal counter to ensure uniqueness.
70- /// </summary>
71- /// <param name="prefix">String to be prepended to the result</param>
72- public string GetNextTagMarker ( string prefix )
73- {
74- return $ "{ prefix } _{ TagMarker } _{ _stepNumber ++ } ";
75- }
76-
77- private static string NewIdentiferTag ( )
78- => $ "{ Constants . TagStart } { Guid . NewGuid ( ) : N} { Constants . TagEnd } ";
79-
80- /// <summary>
81- /// Used to store values for handlers that needs to survive only a single wiki processing session.
82- /// </summary>
83- public void SetStateValue < T > ( string key , T value )
84- {
85- if ( value == null )
86- {
87- return ;
88- }
89- _handlerState [ key ] = value ;
90- }
91-
92- /// <summary>
93- /// Used to get values for handlers that needs to survive only a single wiki processing session.
94- /// </summary>
95- public T GetStateValue < T > ( string key , T defaultValue )
96- {
97- if ( _handlerState . TryGetValue ( key , out var value ) )
98- {
99- return ( T ) value ;
100- }
101- SetStateValue ( key , defaultValue ) ;
102- return defaultValue ;
103- }
104-
105- /// <summary>
106- /// Used to get values for handlers that needs to survive only a single wiki processing session.
107- /// </summary>
108- public bool TryGetStateValue < T > ( string key , [ MaybeNullWhen ( false ) ] out T ? outValue )
109- {
110- if ( _handlerState . TryGetValue ( key , out var value ) )
111- {
112- outValue = ( T ) value ;
113- return true ;
114- }
115-
116- outValue = default ;
117- return false ;
118- }
119-
12069 /// <summary>
12170 /// Creates a new instance of the TightEngineState class. Typically created by a call to TightEngine.Transform().
12271 /// </summary>
@@ -225,6 +174,8 @@ internal async Task<ITwEngineState> Transform()
225174 await handler . Handle ( this ) ;
226175 }
227176
177+ Console . WriteLine ( $ "{ MatchCount : n0} ") ;
178+
228179 return this ;
229180 }
230181
@@ -386,6 +337,14 @@ private async Task TransformScopeFunctionBlock(TwString pageContent, bool onlyPr
386337
387338 foreach ( var match in orderedMatches )
388339 {
340+ if ( _storeAllMatchCache . Contains ( match . Value ) )
341+ {
342+ //When we replace all matches, we keep track of the matches we have already
343+ // replaced in a cache to avoid processing the same match multiple times in
344+ // the same processing session since there is nothing left to replace,
345+ continue ;
346+ }
347+
389348 var parsedFunction = ParsedFunction . Parse ( match . Value ) ;
390349
391350 try
@@ -437,6 +396,14 @@ private async Task TransformMarkup(TwString pageContent, bool onlyProcessFirstCh
437396
438397 foreach ( var match in orderedMatches )
439398 {
399+ if ( _storeAllMatchCache . Contains ( match . Value ) )
400+ {
401+ //When we replace all matches, we keep track of the matches we have already
402+ // replaced in a cache to avoid processing the same match multiple times in
403+ // the same processing session since there is nothing left to replace,
404+ continue ;
405+ }
406+
440407 var result = await handler . Handle ( this , match ) ;
441408 if ( ! result . Instructions . Contains ( TwResultInstruction . Skip ) )
442409 {
@@ -461,6 +428,14 @@ private async Task TransformProcessingInstructionFunctions(TwString pageContent)
461428
462429 foreach ( var match in orderedMatches )
463430 {
431+ if ( _storeAllMatchCache . Contains ( match . Value ) )
432+ {
433+ //When we replace all matches, we keep track of the matches we have already
434+ // replaced in a cache to avoid processing the same match multiple times in
435+ // the same processing session since there is nothing left to replace,
436+ continue ;
437+ }
438+
464439 var parsedFunction = ParsedFunction . Parse ( match . Value ) ;
465440
466441 try
@@ -491,6 +466,14 @@ private async Task TransformStandardFunctions(TwString pageContent, bool onlyPro
491466
492467 foreach ( var match in orderedMatches )
493468 {
469+ if ( _storeAllMatchCache . Contains ( match . Value ) )
470+ {
471+ //When we replace all matches, we keep track of the matches we have already
472+ // replaced in a cache to avoid processing the same match multiple times in
473+ // the same processing session since there is nothing left to replace,
474+ continue ;
475+ }
476+
494477 var parsedFunction = ParsedFunction . Parse ( match . Value ) ;
495478
496479 try
@@ -535,6 +518,14 @@ private async Task TransformPostProcessingFunctions(TwString pageContent)
535518
536519 foreach ( var match in orderedMatches )
537520 {
521+ if ( _storeAllMatchCache . Contains ( match . Value ) )
522+ {
523+ //When we replace all matches, we keep track of the matches we have already
524+ // replaced in a cache to avoid processing the same match multiple times in
525+ // the same processing session since there is nothing left to replace,
526+ continue ;
527+ }
528+
538529 var parsedFunction = ParsedFunction . Parse ( match . Value ) ;
539530
540531 try
@@ -615,6 +606,7 @@ private void StoreHandlerResult(TwPluginResult result, TwMatchType matchType, Tw
615606 }
616607 else
617608 {
609+ _storeAllMatchCache . Add ( matchValue ) ;
618610 identifier = StoreMatch ( matchType , pageContent , matchValue , result . Content , allowNestedDecode ) ;
619611 }
620612
@@ -711,5 +703,57 @@ private string StoreFirstMatch(TwMatchType matchType, TwString pageContent, stri
711703
712704 return identifier ;
713705 }
706+
707+ /// <summary>
708+ /// Gets the next string to use for generating unique tag identifiers during processing, incrementing the internal counter to ensure uniqueness.
709+ /// </summary>
710+ /// <param name="prefix">String to be prepended to the result</param>
711+ public string GetNextTagMarker ( string prefix )
712+ {
713+ return $ "{ prefix } _{ TagMarker } _{ _stepNumber ++ } ";
714+ }
715+
716+ private static string NewIdentiferTag ( )
717+ => $ "{ Constants . TagStart } { Guid . NewGuid ( ) : N} { Constants . TagEnd } ";
718+
719+ /// <summary>
720+ /// Used to store values for handlers that needs to survive only a single wiki processing session.
721+ /// </summary>
722+ public void SetStateValue < T > ( string key , T value )
723+ {
724+ if ( value == null )
725+ {
726+ return ;
727+ }
728+ _handlerState [ key ] = value ;
729+ }
730+
731+ /// <summary>
732+ /// Used to get values for handlers that needs to survive only a single wiki processing session.
733+ /// </summary>
734+ public T GetStateValue < T > ( string key , T defaultValue )
735+ {
736+ if ( _handlerState . TryGetValue ( key , out var value ) )
737+ {
738+ return ( T ) value ;
739+ }
740+ SetStateValue ( key , defaultValue ) ;
741+ return defaultValue ;
742+ }
743+
744+ /// <summary>
745+ /// Used to get values for handlers that needs to survive only a single wiki processing session.
746+ /// </summary>
747+ public bool TryGetStateValue < T > ( string key , [ MaybeNullWhen ( false ) ] out T ? outValue )
748+ {
749+ if ( _handlerState . TryGetValue ( key , out var value ) )
750+ {
751+ outValue = ( T ) value ;
752+ return true ;
753+ }
754+
755+ outValue = default ;
756+ return false ;
757+ }
714758 }
715759}
0 commit comments