@@ -107,6 +107,9 @@ variables:
107107 # '@' followed by a pattern like \S but excluding literal '*' and '@'.
108108 jsdoc_block_tag : \@[^\n\t\f\v *@]+
109109
110+ leading_wspace : (?:^\s*)
111+ trailing_wspace : (?:\s*$\n?)
112+
110113contexts :
111114 main :
112115 - meta_include_prototype : false # don't match comments before shebang
@@ -1011,8 +1014,7 @@ contexts:
10111014 - include : decorator-name
10121015 - include : object-property
10131016
1014- - match : (?=`)
1015- push : literal-string-template
1017+ - include : literal-string-templates
10161018
10171019 - match : (?={{function_call_after_lookahead}})
10181020 push : function-call-arguments
@@ -1078,8 +1080,7 @@ contexts:
10781080 left-expression-end :
10791081 - include : expression-break
10801082
1081- - match : (?=`)
1082- push : literal-string-template
1083+ - include : literal-string-templates
10831084
10841085 - match : ' {{function_call_after_lookahead}}'
10851086 push : function-call-arguments
@@ -1223,16 +1224,76 @@ contexts:
12231224 pop : 1
12241225 - include : string-content
12251226
1227+ literal-string-templates :
1228+ - match : (?=(?:{{identifier_name}}\s*)?`)
1229+ push : literal-string-template
1230+
12261231 literal-string-template :
1227- - match : \`
1228- scope : punctuation.definition.string.begin.js
1232+ # Notes:
1233+ # Consume trailing whitespace after opening punctuation
1234+ # and leading whitespace in front of closing punctuation
1235+ # to maintain JavaScript indentation rules until embedded
1236+ # code really begins/ends. It's required for embedded code
1237+ # to be indented using global JavaScript indentation rules.
1238+ - match : (css)\s*((\`){{trailing_wspace}}?)
1239+ captures :
1240+ 1 : variable.function.tagged-template.js
1241+ 2 : meta.string.js string.quoted.other.js
1242+ 3 : punctuation.definition.string.begin.js
1243+ embed : scope:source.css.js-template
1244+ embed_scope : meta.string.js source.css.embedded.js
1245+ escape : ' {{leading_wspace}}?(\`)'
1246+ escape_captures :
1247+ 0 : meta.string.js string.quoted.other.js
1248+ 1 : punctuation.definition.string.end.js
1249+ pop : 1
1250+ - match : (html)\s*((\`){{trailing_wspace}}?)
1251+ captures :
1252+ 1 : variable.function.tagged-template.js
1253+ 2 : meta.string.js string.quoted.other.js
1254+ 3 : punctuation.definition.string.begin.js
1255+ embed : scope:text.html.js-template
1256+ embed_scope : meta.string.js text.html.embedded.js
1257+ escape : ' {{leading_wspace}}?(\`)'
1258+ escape_captures :
1259+ 0 : meta.string.js string.quoted.other.js
1260+ 1 : punctuation.definition.string.end.js
1261+ pop : 1
1262+ - match : (js)\s*((\`){{trailing_wspace}}?)
1263+ captures :
1264+ 1 : variable.function.tagged-template.js
1265+ 2 : meta.string.js string.quoted.other.js
1266+ 3 : punctuation.definition.string.begin.js
1267+ embed : scope:source.js.js-template
1268+ embed_scope : meta.string.js source.js.embedded.js
1269+ escape : ' {{leading_wspace}}?(\`)'
1270+ escape_captures :
1271+ 0 : meta.string.js string.quoted.other.js
1272+ 1 : punctuation.definition.string.end.js
1273+ pop : 1
1274+ - match : (json)\s*((\`){{trailing_wspace}}?)
1275+ captures :
1276+ 1 : variable.function.tagged-template.js
1277+ 2 : meta.string.js string.quoted.other.js
1278+ 3 : punctuation.definition.string.begin.js
1279+ embed : scope:source.json.js-template
1280+ embed_scope : meta.string.js source.json.embedded.js
1281+ escape : ' {{leading_wspace}}?(\`)'
1282+ escape_captures :
1283+ 0 : meta.string.js string.quoted.other.js
1284+ 1 : punctuation.definition.string.end.js
1285+ pop : 1
1286+ - match : (?:({{identifier_name}})\s*)?(\`)
1287+ captures :
1288+ 1 : variable.function.tagged-template.js
1289+ 2 : meta.string.js string.quoted.other.js punctuation.definition.string.begin.js
12291290 set : literal-string-template-content
12301291
12311292 literal-string-template-content :
12321293 - meta_include_prototype : false
1233- - meta_scope : meta.string.js string.quoted.other.js
1294+ - meta_content_scope : meta.string.js string.quoted.other.js
12341295 - match : \`
1235- scope : punctuation.definition.string.end.js
1296+ scope : meta.string.js string.quoted.other.js punctuation.definition.string.end.js
12361297 pop : 1
12371298 - include : string-interpolations
12381299 - include : string-content
@@ -1250,13 +1311,22 @@ contexts:
12501311
12511312 string-interpolation-content :
12521313 - clear_scopes : 1
1314+ - meta_scope : meta.interpolation.js
1315+ - meta_content_scope : source.js.embedded
1316+ - include : text-interpolation-content
1317+
1318+ text-interpolations :
1319+ - match : \$\{
1320+ scope : punctuation.section.interpolation.begin.js
1321+ push : text-interpolation-content
1322+
1323+ text-interpolation-content :
12531324 - meta_scope : meta.interpolation.js
12541325 - meta_content_scope : source.js.embedded
12551326 - match : \}
12561327 scope : punctuation.section.interpolation.end.js
12571328 pop : 1
1258- - match : (?=\S)
1259- push : expression
1329+ - include : expressions
12601330
12611331 regexp-complete :
12621332 - match : ' /'
@@ -2088,9 +2158,7 @@ contexts:
20882158 - function-name-meta
20892159 - literal-variable-base
20902160
2091- - match : ' {{identifier_name}}(?={{nothing}}`)'
2092- scope : variable.function.tagged-template.js
2093- pop : 1
2161+ - include : literal-string-template
20942162
20952163 - match : ' {{constant_identifier}}(?=\s*(?:{{dot_accessor}}|\[))'
20962164 scope : support.class.js
@@ -2523,9 +2591,7 @@ contexts:
25232591 - match : ' (?=#?{{identifier_name}}{{function_call_after_lookahead}})'
25242592 set : call-method-name
25252593
2526- - match : ' {{identifier_name}}(?={{nothing}}`)'
2527- scope : variable.function.tagged-template.js
2528- pop : 1
2594+ - include : literal-string-template
25292595
25302596 - include : object-property-base
25312597 - include : else-pop
0 commit comments