@@ -96,112 +96,174 @@ class PostRenderEscape {
9696 let swig_tag_name_end = false ;
9797 let swig_tag_name = '' ;
9898 let swig_full_tag_start_buffer = '' ;
99+ // current we just consider one level of string quote
100+ let swig_string_quote = '' ;
99101
100102 const { length } = str ;
101103
102- for ( let idx = 0 ; idx < length ; idx ++ ) {
103- const char = str [ idx ] ;
104- const next_char = str [ idx + 1 ] ;
104+ let idx = 0 ;
105105
106- if ( state === STATE_PLAINTEXT ) { // From plain text to swig
107- if ( char === '{' ) {
108- // check if it is a complete tag {{ }}
109- if ( next_char === '{' ) {
110- state = STATE_SWIG_VAR ;
111- idx ++ ;
112- } else if ( next_char === '#' ) {
113- state = STATE_SWIG_COMMENT ;
114- idx ++ ;
115- } else if ( next_char === '%' ) {
116- state = STATE_SWIG_TAG ;
117- idx ++ ;
118- swig_tag_name = '' ;
119- swig_full_tag_start_buffer = '' ;
120- swig_tag_name_begin = false ; // Mark if it is the first non white space char in the swig tag
121- swig_tag_name_end = false ;
106+ // for backtracking
107+ const swig_start_idx = {
108+ [ STATE_SWIG_VAR ] : 0 ,
109+ [ STATE_SWIG_COMMENT ] : 0 ,
110+ [ STATE_SWIG_TAG ] : 0 ,
111+ [ STATE_SWIG_FULL_TAG ] : 0
112+ } ;
113+
114+ while ( idx < length ) {
115+ while ( idx < length ) {
116+ const char = str [ idx ] ;
117+ const next_char = str [ idx + 1 ] ;
118+
119+ if ( state === STATE_PLAINTEXT ) { // From plain text to swig
120+ if ( char === '{' ) {
121+ // check if it is a complete tag {{ }}
122+ if ( next_char === '{' ) {
123+ state = STATE_SWIG_VAR ;
124+ idx ++ ;
125+ swig_start_idx [ state ] = idx ;
126+ } else if ( next_char === '#' ) {
127+ state = STATE_SWIG_COMMENT ;
128+ idx ++ ;
129+ swig_start_idx [ state ] = idx ;
130+ } else if ( next_char === '%' ) {
131+ state = STATE_SWIG_TAG ;
132+ idx ++ ;
133+ swig_tag_name = '' ;
134+ swig_full_tag_start_buffer = '' ;
135+ swig_tag_name_begin = false ; // Mark if it is the first non white space char in the swig tag
136+ swig_tag_name_end = false ;
137+ swig_start_idx [ state ] = idx ;
138+ } else {
139+ output . append ( char ) ;
140+ }
122141 } else {
123142 output . append ( char ) ;
124143 }
125- } else {
126- output . append ( char ) ;
127- }
128- } else if ( state === STATE_SWIG_TAG ) {
129- if ( char === '%' && next_char === '}' ) { // From swig back to plain text
130- idx ++ ;
131- if ( swig_tag_name !== '' && str . includes ( `end${ swig_tag_name } ` ) ) {
132- state = STATE_SWIG_FULL_TAG ;
133- } else {
144+ } else if ( state === STATE_SWIG_TAG ) {
145+ if ( char === '"' || char === '\'' ) {
146+ if ( swig_string_quote === '' ) {
147+ swig_string_quote = char ;
148+ } else if ( swig_string_quote === char ) {
149+ swig_string_quote = '' ;
150+ }
151+ }
152+ // {% } or {% %
153+ if ( ( ( char !== '%' && next_char === '}' ) || ( char === '%' && next_char !== '}' ) ) && swig_string_quote === '' ) {
154+ // From swig back to plain text
134155 swig_tag_name = '' ;
135156 state = STATE_PLAINTEXT ;
136- output . append ( PostRenderEscape . escapeContent ( this . stored , 'swig' , `{%${ buffer } %}` ) ) ;
137- }
138-
139- buffer = '' ;
140- } else {
141- buffer = buffer + char ;
142- swig_full_tag_start_buffer = swig_full_tag_start_buffer + char ;
143-
144- if ( isNonWhiteSpaceChar ( char ) ) {
145- if ( ! swig_tag_name_begin && ! swig_tag_name_end ) {
146- swig_tag_name_begin = true ;
157+ output . append ( `{%${ buffer } ${ char } ` ) ;
158+ buffer = '' ;
159+ } else if ( char === '%' && next_char === '}' && swig_string_quote === '' ) { // From swig back to plain text
160+ idx ++ ;
161+ if ( swig_tag_name !== '' && str . includes ( `end ${ swig_tag_name } ` ) ) {
162+ state = STATE_SWIG_FULL_TAG ;
163+ swig_start_idx [ state ] = idx ;
164+ } else {
165+ swig_tag_name = '' ;
166+ state = STATE_PLAINTEXT ;
167+ output . append ( PostRenderEscape . escapeContent ( this . stored , 'swig' , `{% ${ buffer } %}` ) ) ;
147168 }
148169
149- if ( swig_tag_name_begin ) {
150- swig_tag_name += char ;
151- }
170+ buffer = '' ;
152171 } else {
153- if ( swig_tag_name_begin === true ) {
154- swig_tag_name_begin = false ;
155- swig_tag_name_end = true ;
172+ buffer = buffer + char ;
173+ swig_full_tag_start_buffer = swig_full_tag_start_buffer + char ;
174+
175+ if ( isNonWhiteSpaceChar ( char ) ) {
176+ if ( ! swig_tag_name_begin && ! swig_tag_name_end ) {
177+ swig_tag_name_begin = true ;
178+ }
179+
180+ if ( swig_tag_name_begin ) {
181+ swig_tag_name += char ;
182+ }
183+ } else {
184+ if ( swig_tag_name_begin === true ) {
185+ swig_tag_name_begin = false ;
186+ swig_tag_name_end = true ;
187+ }
156188 }
157189 }
158- }
159- } else if ( state === STATE_SWIG_VAR ) {
160- if ( char === '}' && next_char === '}' ) {
161- idx ++ ;
162- state = STATE_PLAINTEXT ;
163- output . append ( PostRenderEscape . escapeContent ( this . stored , 'swig' , `{{${ buffer } }}` ) ) ;
164- buffer = '' ;
165- } else {
166- buffer = buffer + char ;
167- }
168- } else if ( state === STATE_SWIG_COMMENT ) { // From swig back to plain text
169- if ( char === '#' && next_char === '}' ) {
170- idx ++ ;
171- state = STATE_PLAINTEXT ;
172- buffer = '' ;
173- }
174- } else if ( state === STATE_SWIG_FULL_TAG ) {
175- if ( char === '{' && next_char === '%' ) {
176- let swig_full_tag_end_buffer = '' ;
177-
178- let _idx = idx + 2 ;
179- for ( ; _idx < length ; _idx ++ ) {
180- const _char = str [ _idx ] ;
181- const _next_char = str [ _idx + 1 ] ;
182-
183- if ( _char === '%' && _next_char === '}' ) {
184- _idx ++ ;
185- break ;
190+ } else if ( state === STATE_SWIG_VAR ) {
191+ if ( char === '"' || char === '\'' ) {
192+ if ( swig_string_quote === '' ) {
193+ swig_string_quote = char ;
194+ } else if ( swig_string_quote === char ) {
195+ swig_string_quote = '' ;
186196 }
187-
188- swig_full_tag_end_buffer = swig_full_tag_end_buffer + _char ;
189197 }
190-
191- if ( swig_full_tag_end_buffer . includes ( `end${ swig_tag_name } ` ) ) {
198+ // {{ }
199+ if ( char === '}' && next_char !== '}' && swig_string_quote === '' ) {
200+ // From swig back to plain text
201+ state = STATE_PLAINTEXT ;
202+ output . append ( `{{${ buffer } ${ char } ` ) ;
203+ buffer = '' ;
204+ } else if ( char === '}' && next_char === '}' && swig_string_quote === '' ) {
205+ idx ++ ;
206+ state = STATE_PLAINTEXT ;
207+ output . append ( PostRenderEscape . escapeContent ( this . stored , 'swig' , `{{${ buffer } }}` ) ) ;
208+ buffer = '' ;
209+ } else {
210+ buffer = buffer + char ;
211+ }
212+ } else if ( state === STATE_SWIG_COMMENT ) { // From swig back to plain text
213+ if ( char === '#' && next_char === '}' ) {
214+ idx ++ ;
192215 state = STATE_PLAINTEXT ;
193- output . append ( PostRenderEscape . escapeContent ( this . stored , 'swig' , `{%${ swig_full_tag_start_buffer } %}${ buffer } {%${ swig_full_tag_end_buffer } %}` ) ) ;
194- idx = _idx ;
195- swig_full_tag_start_buffer = '' ;
196- swig_full_tag_end_buffer = '' ;
197216 buffer = '' ;
217+ }
218+ } else if ( state === STATE_SWIG_FULL_TAG ) {
219+ if ( char === '{' && next_char === '%' ) {
220+ let swig_full_tag_end_buffer = '' ;
221+ let swig_full_tag_found = false ;
222+
223+ let _idx = idx + 2 ;
224+ for ( ; _idx < length ; _idx ++ ) {
225+ const _char = str [ _idx ] ;
226+ const _next_char = str [ _idx + 1 ] ;
227+
228+ if ( _char === '%' && _next_char === '}' ) {
229+ _idx ++ ;
230+ swig_full_tag_found = true ;
231+ break ;
232+ }
233+
234+ swig_full_tag_end_buffer = swig_full_tag_end_buffer + _char ;
235+ }
236+
237+ if ( swig_full_tag_found && swig_full_tag_end_buffer . includes ( `end${ swig_tag_name } ` ) ) {
238+ state = STATE_PLAINTEXT ;
239+ output . append ( PostRenderEscape . escapeContent ( this . stored , 'swig' , `{%${ swig_full_tag_start_buffer } %}${ buffer } {%${ swig_full_tag_end_buffer } %}` ) ) ;
240+ idx = _idx ;
241+ swig_full_tag_start_buffer = '' ;
242+ swig_full_tag_end_buffer = '' ;
243+ buffer = '' ;
244+ } else {
245+ buffer += char ;
246+ }
198247 } else {
199248 buffer += char ;
200249 }
201- } else {
202- buffer += char ;
203250 }
251+ idx ++ ;
252+ }
253+ if ( state === STATE_PLAINTEXT ) {
254+ break ;
255+ }
256+ // If the swig tag is not closed, then it is a plain text, we need to backtrack
257+ idx = swig_start_idx [ state ] ;
258+ buffer = '' ;
259+ swig_string_quote = '' ;
260+ if ( state === STATE_SWIG_FULL_TAG ) {
261+ output . append ( `{%${ swig_full_tag_start_buffer } %` ) ;
262+ } else {
263+ output . append ( '{' ) ;
204264 }
265+ swig_full_tag_start_buffer = '' ;
266+ state = STATE_PLAINTEXT ;
205267 }
206268
207269 return output . toString ( ) ;
0 commit comments