@@ -185,47 +185,82 @@ export class Parser {
185185 location , absoluteOffset , this . errors ) ;
186186 }
187187
188+ /**
189+ * Splits a string of text into "raw" text segments and expressions present in interpolations in
190+ * the string.
191+ * Returns `null` if there are no interpolations, otherwise a
192+ * `SplitInterpolation` with splits that look like
193+ * <raw text> <expression> <raw text> ... <raw text> <expression> <raw text>
194+ */
188195 splitInterpolation (
189196 input : string , location : string ,
190197 interpolationConfig : InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG ) : SplitInterpolation
191198 | null {
192- const regexp = _getInterpolateRegExp ( interpolationConfig ) ;
193- const parts = input . split ( regexp ) ;
194- if ( parts . length <= 1 ) {
195- return null ;
196- }
197199 const strings : string [ ] = [ ] ;
198200 const expressions : string [ ] = [ ] ;
199201 const offsets : number [ ] = [ ] ;
200202 const stringSpans : { start : number , end : number } [ ] = [ ] ;
201203 const expressionSpans : { start : number , end : number } [ ] = [ ] ;
202- let offset = 0 ;
203- for ( let i = 0 ; i < parts . length ; i ++ ) {
204- const part : string = parts [ i ] ;
205- if ( i % 2 === 0 ) {
206- // fixed string
204+ let i = 0 ;
205+ let atInterpolation = false ;
206+ let extendLastString = false ;
207+ let { start : interpStart , end : interpEnd } = interpolationConfig ;
208+ while ( i < input . length ) {
209+ if ( ! atInterpolation ) {
210+ // parse until starting {{
211+ const start = i ;
212+ i = input . indexOf ( interpStart , i ) ;
213+ if ( i === - 1 ) {
214+ i = input . length ;
215+ }
216+ const part = input . substring ( start , i ) ;
207217 strings . push ( part ) ;
208- const start = offset ;
209- offset += part . length ;
210- stringSpans . push ( { start, end : offset } ) ;
211- } else if ( part . trim ( ) . length > 0 ) {
212- const start = offset ;
213- offset += interpolationConfig . start . length ;
214- expressions . push ( part ) ;
215- offsets . push ( offset ) ;
216- offset += part . length + interpolationConfig . end . length ;
217- expressionSpans . push ( { start, end : offset } ) ;
218+ stringSpans . push ( { start, end : i } ) ;
219+
220+ atInterpolation = true ;
221+ } else {
222+ // parse from starting {{ to ending }}
223+ const fullStart = i ;
224+ const exprStart = fullStart + interpStart . length ;
225+ const exprEnd = input . indexOf ( interpEnd , exprStart ) ;
226+ if ( exprEnd === - 1 ) {
227+ // Could not find the end of the interpolation; do not parse an expression.
228+ // Instead we should extend the content on the last raw string.
229+ atInterpolation = false ;
230+ extendLastString = true ;
231+ break ;
232+ }
233+ const fullEnd = exprEnd + interpEnd . length ;
234+
235+ const part = input . substring ( exprStart , exprEnd ) ;
236+ if ( part . trim ( ) . length > 0 ) {
237+ expressions . push ( part ) ;
238+ } else {
239+ this . _reportError (
240+ 'Blank expressions are not allowed in interpolated strings' , input ,
241+ `at column ${ i } in` , location ) ;
242+ expressions . push ( '$implicit' ) ;
243+ }
244+ offsets . push ( exprStart ) ;
245+ expressionSpans . push ( { start : fullStart , end : fullEnd } ) ;
246+
247+ i = fullEnd ;
248+ atInterpolation = false ;
249+ }
250+ }
251+ if ( ! atInterpolation ) {
252+ // If we are now at a text section, add the remaining content as a raw string.
253+ if ( extendLastString ) {
254+ strings [ strings . length - 1 ] += input . substring ( i ) ;
255+ stringSpans [ stringSpans . length - 1 ] . end = input . length ;
218256 } else {
219- this . _reportError (
220- 'Blank expressions are not allowed in interpolated strings' , input ,
221- `at column ${ this . _findInterpolationErrorColumn ( parts , i , interpolationConfig ) } in` ,
222- location ) ;
223- expressions . push ( '$implicit' ) ;
224- offsets . push ( offset ) ;
225- expressionSpans . push ( { start : offset , end : offset } ) ;
257+ strings . push ( input . substring ( i ) ) ;
258+ stringSpans . push ( { start : i , end : input . length } ) ;
226259 }
227260 }
228- return new SplitInterpolation ( strings , stringSpans , expressions , expressionSpans , offsets ) ;
261+ return expressions . length === 0 ?
262+ null :
263+ new SplitInterpolation ( strings , stringSpans , expressions , expressionSpans , offsets ) ;
229264 }
230265
231266 wrapLiteralPrimitive ( input : string | null , location : any , absoluteOffset : number ) : ASTWithSource {
0 commit comments