Skip to content

Commit 1dac73b

Browse files
authored
VSCode: Extra goodies for Svelte TM grammar (#802)
* New highlighting for `$:` reactive statements in scripts * New highlighting of the `$` symbol in `$var` store accessors in scripts * Updated highlighting for element directives (more specific `bind:` and `class:` highlighting) * Bugfix / redo of how 'unit' (e.g. `4px`) unquoted strings are highlighted
1 parent eb23517 commit 1dac73b

File tree

2 files changed

+54
-18
lines changed

2 files changed

+54
-18
lines changed

packages/svelte-vscode/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,8 @@
485485
]
486486
},
487487
"devDependencies": {
488-
"@types/lodash": "^4.14.116",
489488
"@tsconfig/node12": "^1.0.0",
489+
"@types/lodash": "^4.14.116",
490490
"@types/node": "^13.9.0",
491491
"@types/vscode": "*",
492492
"js-yaml": "^3.14.0",

packages/svelte-vscode/syntaxes/svelte.tmLanguage.src.yaml

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ injections:
8686

8787
# ---- LANGUAGE EXTENSIONS
8888

89+
# - TS / JS / CS -
90+
91+
# Matches `$:` reactive statement symbols, but only in script tags.
92+
# Exclusion of certain meta scopes prevents key literals from conflicting with this scope.
93+
'L:meta.script.svelte (source.ts, source.js, source.coffee) - meta.var - meta.objectliteral':
94+
patterns:
95+
- match: ^\s*(\$)(:)
96+
captures:
97+
1: { name: keyword.control.svelte }
98+
2: { name: punctuation.definition.keyword.svelte }
99+
100+
'L:(source.ts, source.js, source.coffee)':
101+
patterns:
102+
# Matches the store accessor symbol.
103+
# i.e. the `$` in `$myStore`.
104+
- match: (?<![_$[:alnum:]])\$(?=[_[:alpha:]][_$[:alnum:]]*)
105+
name: punctuation.definition.variable.svelte
106+
# Matches the built-in constants/keywords that Svelte supports.
107+
# e.g. `$$restProps`.
108+
- match: (?<![_$[:alnum:]])(\$\$)(props|restProps|slots)*
109+
captures:
110+
1: { name: punctuation.definition.variable.svelte }
111+
2: { name: support.constant.svelte }
112+
89113
# - PUG -
90114
# TODO: Pug language injections
91115

@@ -115,7 +139,7 @@ repository:
115139
- include: '#tags'
116140
- include: '#interpolation'
117141
# Content text.
118-
# This matches only inbetween all the nodes - nothing inside of them.
142+
# This matches only inbetween all the nodes - nothing inside of them.
119143
- begin: (?<=>|})
120144
end: (?=<|{)
121145
name: text.svelte
@@ -134,15 +158,15 @@ repository:
134158
# Component documentation.
135159
- begin: (@)(component)
136160
beginCaptures:
137-
1: { name: punctuation.definition.keyword }
161+
1: { name: punctuation.definition.keyword.svelte }
138162
2: { name: storage.type.class.component.svelte keyword.declaration.class.component.svelte }
139163
end: (?=-->)
140164
contentName: comment.block.documentation.svelte
141165
patterns:
142166
# The reason we do it like this is so that the Markdown grammar cannot break out of the `-->` bit.
143167
# Embedded languages, for whatever reason, can only break out of begin-end blocks. (...most of the time)
144168
# If you shove them in a match pattern, it cannot break out of it's matched bounds.
145-
# And since the match consumed the line leading to `-->`,
169+
# And since the match consumed the line leading to `-->`,
146170
# the 'block' markdown won't break out of the comment block.
147171
- match: .*?(?=-->)
148172
captures: { 0: { patterns: [ include: text.html.markdown ] } }
@@ -269,7 +293,7 @@ repository:
269293
# Special void tags like `{:else}` and `{@html}`.
270294
special-tags-void:
271295
begin: ({)\s*((?:[@:])(else\s+if|[a-z]*))
272-
beginCaptures:
296+
beginCaptures:
273297
1: { name: punctuation.definition.block.begin.svelte }
274298
2: { patterns: [ include: '#special-tags-keywords' ] }
275299
end: \}
@@ -288,7 +312,7 @@ repository:
288312
begin: ({)\s*(#([a-z]*))
289313
end: (})
290314
name: meta.special.$3.svelte meta.special.start.svelte
291-
beginCaptures:
315+
beginCaptures:
292316
1: { name: punctuation.definition.block.begin.svelte }
293317
2: { patterns: [ include: '#special-tags-keywords' ] }
294318
endCaptures: { 0: { name: punctuation.definition.block.end.svelte } }
@@ -340,8 +364,8 @@ repository:
340364
patterns:
341365
# No quotes - just an interpolation expression.
342366
- include: '#interpolation'
343-
# Pure digits / numbers.
344-
- match: ([0-9._]|/(?!>))+
367+
# Units, meaning digit characters and an optional unit string. e.g. `15px`
368+
- match: ([0-9._]+[\w]{,4})(?=\s|/?>)
345369
name: constant.numeric.decimal.svelte
346370
patterns: [ include: '#interpolation' ]
347371
# Unquoted strings.
@@ -361,33 +385,45 @@ repository:
361385
patterns:
362386
# If other keywords are patched in in the future, they can be added here but also need to be added
363387
# where attributes-directives-keywords is included.
364-
- { match: on|use|bind, name: keyword.control.svelte }
365-
- { match: transition|in|out|animate, name: keyword.other.animation.svelte }
366-
- { match: let, name: storage.type.svelte }
388+
- { match: on|use|bind, name: keyword.control.svelte }
389+
- { match: transition|in|out|animate, name: keyword.other.animation.svelte }
390+
- { match: let, name: storage.type.svelte }
367391
- { match: class, name: entity.other.attribute-name.svelte }
368392

369393
# For Svelte element directives. Scopes the 'click' part in `on:click`.
370394
# The scope of the variable should represent what data type it generally is.
371395
attributes-directives-types:
372396
patterns:
373397
# If other keywords are patched in in the future, they can easily be added here.
398+
- { match: '(?<=(on):).*$', name: entity.name.type.svelte }
399+
- { match: '(?<=(bind):).*$', name: variable.parameter.svelte }
400+
- { match: '(?<=(use|transition|in|out|animate):).*$', name: variable.function.svelte }
401+
- { match: '(?<=(let|class):).*$', name: variable.parameter.svelte }
402+
403+
# For directives that may be better suited using different scopes if assigned to something.
404+
# e.g. `class:var={var}` is different to `class:var`.
405+
# In the latter, `var` is a variable identifier and not a CSS class name.
406+
attributes-directives-types-assigned:
407+
patterns:
374408
# Special Cases
375409
# Makes 'bind:this' display like `this` would in JS.
376410
- { match: '(?<=(bind):)this$', name: variable.language.svelte }
377-
# Generic
378-
- { match: '(?<=(on|bind):).*$', name: entity.name.type.svelte }
379-
- { match: '(?<=(use|transition|in|out|animate):).*$', name: variable.function.svelte }
380-
- { match: '(?<=(let|class):).*$', name: variable.parameter.svelte }
411+
# If other keywords are patched in in the future, they can easily be added here.
412+
- { match: '(?<=(bind):).*$', name: entity.name.type.svelte }
413+
- { match: '(?<=(class):).*$', name: entity.other.attribute-name.class.svelte }
414+
# Defaults to the non-assignment version for everything else.
415+
- include: '#attributes-directives-types'
381416

382417
# Matches Svelte element directives, e.g. `on:click|preventDefault={var}`
383418
attributes-directives:
384419
# If something is added to attributes-directives-keywords, it must be added to the begin-regex, too.
385-
begin: (?<!<)(on|use|bind|transition|in|out|animate|let|class)(:)([_$[:alpha:]][_\-$[:alnum:]]*)((\|\w+)*)
420+
begin: (?<!<)(on|use|bind|transition|in|out|animate|let|class)(:)(?:([_$[:alpha:]][_\-$[:alnum:]]*(?=\s*=))|([_$[:alpha:]][_\-$[:alnum:]]*))((\|\w+)*)
386421
beginCaptures:
387422
1: { patterns: [ include: '#attributes-directives-keywords' ] }
388423
2: { name: punctuation.definition.keyword.svelte }
389-
3: { patterns: [ include: '#attributes-directives-types' ] }
390-
4: { patterns: [
424+
3: { patterns: [ include: '#attributes-directives-types-assigned' ] }
425+
4: { patterns: [ include: '#attributes-directives-types' ] }
426+
5: { patterns: [
391427
{ match: '\w+', name: support.function.svelte },
392428
{ match: '\|', name: punctuation.separator.svelte }
393429
]}

0 commit comments

Comments
 (0)