@@ -18,11 +18,11 @@ const rSwigTag = /(\{\{.+?\}\})|(\{#.+?#\})|(\{%.+?%\})/s;
1818const  rSwigPlaceHolder  =  / (?: < | & l t ; ) ! - - s w i g \uFFFC ( \d + ) - - (?: > | & g t ; ) / g; 
1919const  rCodeBlockPlaceHolder  =  / (?: < | & l t ; ) ! - - c o d e \uFFFC ( \d + ) - - (?: > | & g t ; ) / g; 
2020
21- const  STATE_PLAINTEXT  =  Symbol ( 'plaintext' ) ; 
22- const  STATE_SWIG_VAR  =  Symbol ( 'swig_var' ) ; 
23- const  STATE_SWIG_COMMENT  =  Symbol ( 'swig_comment' ) ; 
24- const  STATE_SWIG_TAG  =  Symbol ( 'swig_tag' ) ; 
25- const  STATE_SWIG_FULL_TAG  =  Symbol ( 'swig_full_tag' ) ; 
21+ const  STATE_PLAINTEXT  =  0 ; 
22+ const  STATE_SWIG_VAR  =  1 ; 
23+ const  STATE_SWIG_COMMENT  =  2 ; 
24+ const  STATE_SWIG_TAG  =  3 ; 
25+ const  STATE_SWIG_FULL_TAG  =  4 ; 
2626
2727const  isNonWhiteSpaceChar  =  ( char : string )  =>  char  !==  '\r' 
2828  &&  char  !==  '\n' 
@@ -31,22 +31,6 @@ const isNonWhiteSpaceChar = (char: string) => char !== '\r'
3131  &&  char  !==  '\v' 
3232  &&  char  !==  ' ' ; 
3333
34- class  StringBuilder  { 
35-   private  parts : string [ ] ; 
36- 
37-   constructor ( )  { 
38-     this . parts  =  [ ] ; 
39-   } 
40- 
41-   append ( str : string ) : void   { 
42-     this . parts . push ( str ) ; 
43-   } 
44- 
45-   toString ( ) : string  { 
46-     return  this . parts . join ( '' ) ; 
47-   } 
48- } 
49- 
5034class  PostRenderEscape  { 
5135  public  stored : string [ ] ; 
5236  public  length : number ; 
@@ -87,13 +71,16 @@ class PostRenderEscape {
8771   */ 
8872  escapeAllSwigTags ( str : string )  { 
8973    let  state  =  STATE_PLAINTEXT ; 
90-     let  buffer  =  '' ; 
91-     const  output  =  new  StringBuilder ( ) ; 
74+     let  buffer_start  =  - 1 ; 
75+     let  plain_text_start  =  0 ; 
76+     let  output  =  '' ; 
9277
9378    let  swig_tag_name_begin  =  false ; 
9479    let  swig_tag_name_end  =  false ; 
9580    let  swig_tag_name  =  '' ; 
96-     let  swig_full_tag_start_buffer  =  '' ; 
81+ 
82+     let  swig_full_tag_start_start  =  - 1 ; 
83+     let  swig_full_tag_start_end  =  - 1 ; 
9784    // current we just consider one level of string quote 
9885    let  swig_string_quote  =  '' ; 
9986
@@ -102,11 +89,24 @@ class PostRenderEscape {
10289    let  idx  =  0 ; 
10390
10491    // for backtracking 
105-     const  swig_start_idx  =  { 
106-       [ STATE_SWIG_VAR ] : 0 , 
107-       [ STATE_SWIG_COMMENT ] : 0 , 
108-       [ STATE_SWIG_TAG ] : 0 , 
109-       [ STATE_SWIG_FULL_TAG ] : 0 
92+     const  swig_start_idx  =  [ 0 ,  0 ,  0 ,  0 ,  0 ] ; 
93+ 
94+     const  flushPlainText  =  ( end : number )  =>  { 
95+       if  ( plain_text_start  !==  - 1  &&  end  >  plain_text_start )  { 
96+         output  +=  str . slice ( plain_text_start ,  end ) ; 
97+       } 
98+       plain_text_start  =  - 1 ; 
99+     } ; 
100+ 
101+     const  ensurePlainTextStart  =  ( position : number )  =>  { 
102+       if  ( plain_text_start  ===  - 1 )  { 
103+         plain_text_start  =  position ; 
104+       } 
105+     } ; 
106+ 
107+     const  pushAndReset  =  ( value : string )  =>  { 
108+       output  +=  value ; 
109+       plain_text_start  =  - 1 ; 
110110    } ; 
111111
112112    while  ( idx  <  length )  { 
@@ -115,29 +115,33 @@ class PostRenderEscape {
115115        const  next_char  =  str [ idx  +  1 ] ; 
116116
117117        if  ( state  ===  STATE_PLAINTEXT )  {  // From plain text to swig 
118+           ensurePlainTextStart ( idx ) ; 
118119          if  ( char  ===  '{' )  { 
119120            // check if it is a complete tag {{ }} 
120121            if  ( next_char  ===  '{' )  { 
122+               flushPlainText ( idx ) ; 
121123              state  =  STATE_SWIG_VAR ; 
122124              idx ++ ; 
125+               buffer_start  =  idx  +  1 ; 
123126              swig_start_idx [ state ]  =  idx ; 
124127            }  else  if  ( next_char  ===  '#' )  { 
128+               flushPlainText ( idx ) ; 
125129              state  =  STATE_SWIG_COMMENT ; 
126130              idx ++ ; 
131+               buffer_start  =  idx  +  1 ; 
127132              swig_start_idx [ state ]  =  idx ; 
128133            }  else  if  ( next_char  ===  '%' )  { 
134+               flushPlainText ( idx ) ; 
129135              state  =  STATE_SWIG_TAG ; 
130136              idx ++ ; 
137+               buffer_start  =  idx  +  1 ; 
138+               swig_full_tag_start_start  =  idx  +  1 ; 
139+               swig_full_tag_start_end  =  idx  +  1 ; 
131140              swig_tag_name  =  '' ; 
132-               swig_full_tag_start_buffer  =  '' ; 
133141              swig_tag_name_begin  =  false ;  // Mark if it is the first non white space char in the swig tag 
134142              swig_tag_name_end  =  false ; 
135143              swig_start_idx [ state ]  =  idx ; 
136-             }  else  { 
137-               output . append ( char ) ; 
138144            } 
139-           }  else  { 
140-             output . append ( char ) ; 
141145          } 
142146        }  else  if  ( state  ===  STATE_SWIG_TAG )  { 
143147          if  ( char  ===  '"'  ||  char  ===  '\'' )  { 
@@ -152,24 +156,23 @@ class PostRenderEscape {
152156            // From swig back to plain text 
153157            swig_tag_name  =  '' ; 
154158            state  =  STATE_PLAINTEXT ; 
155-             output . append ( `{%${ buffer } ${ char }  ` ) ; 
156-             buffer  =  '' ; 
159+             pushAndReset ( `{%${ str . slice ( buffer_start ,  idx ) } ${ char }  ` ) ; 
157160          }  else  if  ( char  ===  '%'  &&  next_char  ===  '}'  &&  swig_string_quote  ===  '' )  {  // From swig back to plain text 
158161            idx ++ ; 
159162            if  ( swig_tag_name  !==  ''  &&  str . includes ( `end${ swig_tag_name }  ` ) )  { 
160163              state  =  STATE_SWIG_FULL_TAG ; 
164+               buffer_start  =  idx  +  1 ; 
165+               // since we have already move idx to next char of ' }', so here is idx -1 
166+               swig_full_tag_start_end  =  idx  -  1 ; 
161167              swig_start_idx [ state ]  =  idx ; 
162168            }  else  { 
163169              swig_tag_name  =  '' ; 
164170              state  =  STATE_PLAINTEXT ; 
165-               output . append ( PostRenderEscape . escapeContent ( this . stored ,  'swig' ,  `{%${ buffer }  %}` ) ) ; 
171+               // since we have already move idx to next char of ' }', so here is idx -1 
172+               pushAndReset ( PostRenderEscape . escapeContent ( this . stored ,  'swig' ,  `{%${ str . slice ( buffer_start ,  idx  -  1 ) }  %}` ) ) ; 
166173            } 
167174
168-             buffer  =  '' ; 
169175          }  else  { 
170-             buffer  =  buffer  +  char ; 
171-             swig_full_tag_start_buffer  =  swig_full_tag_start_buffer  +  char ; 
172- 
173176            if  ( isNonWhiteSpaceChar ( char ) )  { 
174177              if  ( ! swig_tag_name_begin  &&  ! swig_tag_name_end )  { 
175178                swig_tag_name_begin  =  true ; 
@@ -197,21 +200,17 @@ class PostRenderEscape {
197200          if  ( char  ===  '}'  &&  next_char  !==  '}'  &&  swig_string_quote  ===  '' )  { 
198201            // From swig back to plain text 
199202            state  =  STATE_PLAINTEXT ; 
200-             output . append ( `{{${ buffer } ${ char }  ` ) ; 
201-             buffer  =  '' ; 
203+             pushAndReset ( `{{${ str . slice ( buffer_start ,  idx ) } ${ char }  ` ) ; 
202204          }  else  if  ( char  ===  '}'  &&  next_char  ===  '}'  &&  swig_string_quote  ===  '' )  { 
205+             pushAndReset ( PostRenderEscape . escapeContent ( this . stored ,  'swig' ,  `{{${ str . slice ( buffer_start ,  idx ) }  }}` ) ) ; 
203206            idx ++ ; 
204207            state  =  STATE_PLAINTEXT ; 
205-             output . append ( PostRenderEscape . escapeContent ( this . stored ,  'swig' ,  `{{${ buffer }  }}` ) ) ; 
206-             buffer  =  '' ; 
207-           }  else  { 
208-             buffer  =  buffer  +  char ; 
209208          } 
210209        }  else  if  ( state  ===  STATE_SWIG_COMMENT )  {  // From swig back to plain text 
211210          if  ( char  ===  '#'  &&  next_char  ===  '}' )  { 
212211            idx ++ ; 
213212            state  =  STATE_PLAINTEXT ; 
214-             buffer  =  '' ; 
213+             plain_text_start  =  - 1 ; 
215214          } 
216215        }  else  if  ( state  ===  STATE_SWIG_FULL_TAG )  { 
217216          if  ( char  ===  '{'  &&  next_char  ===  '%' )  { 
@@ -234,16 +233,10 @@ class PostRenderEscape {
234233
235234            if  ( swig_full_tag_found  &&  swig_full_tag_end_buffer . includes ( `end${ swig_tag_name }  ` ) )  { 
236235              state  =  STATE_PLAINTEXT ; 
237-               output . append ( PostRenderEscape . escapeContent ( this . stored ,  'swig' ,  `{%${ swig_full_tag_start_buffer }  %}${ buffer }  {%${ swig_full_tag_end_buffer }  %}` ) ) ; 
236+               pushAndReset ( PostRenderEscape . escapeContent ( this . stored ,  'swig' ,  `{%${ str . slice ( swig_full_tag_start_start ,   swig_full_tag_start_end ) }  %}${ str . slice ( buffer_start ,   idx ) }  {%${ swig_full_tag_end_buffer }  %}` ) ) ; 
238237              idx  =  _idx ; 
239-               swig_full_tag_start_buffer  =  '' ; 
240238              swig_full_tag_end_buffer  =  '' ; 
241-               buffer  =  '' ; 
242-             }  else  { 
243-               buffer  +=  char ; 
244239            } 
245-           }  else  { 
246-             buffer  +=  char ; 
247240          } 
248241        } 
249242        idx ++ ; 
@@ -252,19 +245,21 @@ class PostRenderEscape {
252245        break ; 
253246      } 
254247      // If the swig tag is not closed, then it is a plain text, we need to backtrack 
255-       idx  =  swig_start_idx [ state ] ; 
256-       buffer  =  '' ; 
257-       swig_string_quote  =  '' ; 
258248      if  ( state  ===  STATE_SWIG_FULL_TAG )  { 
259-         output . append ( `{%${ swig_full_tag_start_buffer }  %` ) ; 
249+         pushAndReset ( `{%${ str . slice ( swig_full_tag_start_start ,   swig_full_tag_start_end ) }  %` ) ; 
260250      }  else  { 
261-         output . append ( '{' ) ; 
251+         pushAndReset ( '{' ) ; 
262252      } 
263-       swig_full_tag_start_buffer  =  '' ; 
253+       idx  =  swig_start_idx [ state ] ; 
254+       swig_string_quote  =  '' ; 
264255      state  =  STATE_PLAINTEXT ; 
265256    } 
266257
267-     return  output . toString ( ) ; 
258+     if  ( plain_text_start  !==  - 1  &&  plain_text_start  <  length )  { 
259+       output  +=  str . slice ( plain_text_start ) ; 
260+     } 
261+ 
262+     return  output ; 
268263  } 
269264} 
270265
0 commit comments