Skip to content

Commit c33a49e

Browse files
authored
feat: add textmate grammar for inline CSS styles (#512)
* feat: add textmate grammar for inline CSS styles Adds a TextMate grammar for inline styles in a component. Unfortunately, we cannot merge this grammar conviniently with the one specified for inline templates, because though the directions of grammar recurse are similar for both, they apply different grammars for matches. For instance, an inline template and style both match a string literal, but the former applies an HTML grammar while the later applies a CSS grammar. To distinguish between the two, we have to create two different grammar recurse paths at the closest divergence of the grammars (for convinience, at `template` and `style` properties in a `@Component` definition). Attached to the PR for this commit are images demonstrating this change. The second image shows that commenting out the style property applies the regular comment grammar to the entire style string. For some reason, however, running a commented style through the snapshot tests leads to an incorrect and undeterministic result. This is likely an issue with the test framework; I will investigate and update the tests in a future PR. Partially addresses #483 ([comment](#483 (comment))) * fixup! feat: add textmate grammar for inline CSS styles * fixup! feat: add textmate grammar for inline CSS styles
1 parent 862585b commit c33a49e

File tree

7 files changed

+241
-1
lines changed

7 files changed

+241
-1
lines changed

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@
5858
"embeddedLanguages": {
5959
"source.html": "html"
6060
}
61+
},
62+
{
63+
"path": "./syntaxes/inline-styles.json",
64+
"scopeName": "inline-styles.ng",
65+
"injectTo": [
66+
"source.ts"
67+
],
68+
"embeddedLanguages": {
69+
"source.css": "css"
70+
}
6171
}
6272
]
6373
},

syntaxes/inline-styles.json

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{
2+
"scopeName": "inline-styles.ng",
3+
"injectionSelector": "L:source.ts#meta.decorator.ts -comment",
4+
"patterns": [
5+
{
6+
"include": "#inline-styles"
7+
}
8+
],
9+
"repository": {
10+
"inline-styles": {
11+
"begin": "(styles)\\s*(:)",
12+
"beginCaptures": {
13+
"1": {
14+
"name": "meta.object-literal.key.ts"
15+
},
16+
"2": {
17+
"name": "meta.object-literal.key.ts punctuation.separator.key-value.ts"
18+
}
19+
},
20+
"end": "(?=,|})",
21+
"patterns": [
22+
{
23+
"include": "#ts-paren-expression"
24+
},
25+
{
26+
"include": "#ts-bracket-expression"
27+
}
28+
]
29+
},
30+
31+
"ts-paren-expression": {
32+
"begin": "\\G\\s*(\\()",
33+
"beginCaptures": {
34+
"1": {
35+
"name": "meta.brace.round.ts"
36+
}
37+
},
38+
"end": "\\)",
39+
"endCaptures": {
40+
"0": {
41+
"name": "meta.brace.round.ts"
42+
}
43+
},
44+
"patterns": [
45+
{
46+
"include": "$self"
47+
},
48+
{
49+
"include": "#ts-bracket-expression"
50+
}
51+
]
52+
},
53+
54+
"ts-bracket-expression": {
55+
"begin": "\\G\\s*(\\[)",
56+
"beginCaptures": {
57+
"1": {
58+
"name": "meta.array.literal.ts meta.brace.square.ts"
59+
}
60+
},
61+
"end": "\\]",
62+
"endCaptures": {
63+
"0": {
64+
"name": "meta.array.literal.ts meta.brace.square.ts"
65+
}
66+
},
67+
"patterns": [
68+
{
69+
"include": "#style"
70+
}
71+
]
72+
},
73+
74+
"style": {
75+
"begin": "\\s*([`|'|\"])",
76+
"beginCaptures": {
77+
"1": {
78+
"name": "string"
79+
}
80+
},
81+
"end": "\\1",
82+
"endCaptures": {
83+
"0": {
84+
"name": "string"
85+
}
86+
},
87+
"contentName": "source.css",
88+
"patterns": [
89+
{
90+
"include": "source.css"
91+
}
92+
]
93+
}
94+
}
95+
}

syntaxes/test/cases.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33
"scopeName": "inline-template.ng",
44
"grammarFiles": ["syntaxes/inline-template.json"],
55
"testFile": "syntaxes/test/data/inline-template.ts"
6+
},
7+
{
8+
"scopeName": "inline-styles.ng",
9+
"grammarFiles": ["syntaxes/inline-styles.json"],
10+
"testFile": "syntaxes/test/data/inline-styles.ts"
611
}
712
]

syntaxes/test/data/inline-styles.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* clang-format off */
2+
3+
@Component({
4+
//// Property key/value test
5+
styles: [ '.example { width: 100px; }' ],
6+
7+
//// Multiple styles test
8+
styles: [
9+
'.example { width: 100px; }',
10+
'.example { height: 100px; }',
11+
],
12+
13+
//// String delimiter tests
14+
styles: [ `.example { width: 100px; }` ],
15+
styles: [ ".example { width: 100px; }" ],
16+
styles: [ '.example { width: 100px; }' ],
17+
18+
//// Parenthesization tests
19+
styles: ( (( [ ( '.example { width: 100px; }' ) ] )) ),
20+
})
21+
export class TMComponent{}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
>/* clang-format off */
2+
#^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng
3+
>
4+
>@Component({
5+
#^^^^^^^^^^^^^ inline-styles.ng
6+
>//// Property key/value test
7+
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng
8+
> styles: [ '.example { width: 100px; }' ],
9+
#^^ inline-styles.ng
10+
# ^^^^^^ inline-styles.ng meta.object-literal.key.ts
11+
# ^ inline-styles.ng meta.object-literal.key.ts punctuation.separator.key-value.ts
12+
# ^ inline-styles.ng
13+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
14+
# ^ inline-styles.ng
15+
# ^ inline-styles.ng string
16+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng source.css
17+
# ^ inline-styles.ng string
18+
# ^ inline-styles.ng
19+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
20+
# ^^ inline-styles.ng
21+
>
22+
>//// Multiple styles test
23+
#^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng
24+
> styles: [
25+
#^^ inline-styles.ng
26+
# ^^^^^^ inline-styles.ng meta.object-literal.key.ts
27+
# ^ inline-styles.ng meta.object-literal.key.ts punctuation.separator.key-value.ts
28+
# ^ inline-styles.ng
29+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
30+
> '.example { width: 100px; }',
31+
#^^^^ inline-styles.ng
32+
# ^ inline-styles.ng string
33+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng source.css
34+
# ^ inline-styles.ng string
35+
# ^^ inline-styles.ng
36+
> '.example { height: 100px; }',
37+
#^^^^ inline-styles.ng
38+
# ^ inline-styles.ng string
39+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng source.css
40+
# ^ inline-styles.ng string
41+
# ^^ inline-styles.ng
42+
> ],
43+
#^^ inline-styles.ng
44+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
45+
# ^^ inline-styles.ng
46+
>
47+
>//// String delimiter tests
48+
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng
49+
> styles: [ `.example { width: 100px; }` ],
50+
#^^ inline-styles.ng
51+
# ^^^^^^ inline-styles.ng meta.object-literal.key.ts
52+
# ^ inline-styles.ng meta.object-literal.key.ts punctuation.separator.key-value.ts
53+
# ^ inline-styles.ng
54+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
55+
# ^ inline-styles.ng
56+
# ^ inline-styles.ng string
57+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng source.css
58+
# ^ inline-styles.ng string
59+
# ^ inline-styles.ng
60+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
61+
# ^^ inline-styles.ng
62+
> styles: [ ".example { width: 100px; }" ],
63+
#^^ inline-styles.ng
64+
# ^^^^^^ inline-styles.ng meta.object-literal.key.ts
65+
# ^ inline-styles.ng meta.object-literal.key.ts punctuation.separator.key-value.ts
66+
# ^ inline-styles.ng
67+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
68+
# ^ inline-styles.ng
69+
# ^ inline-styles.ng string
70+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng source.css
71+
# ^ inline-styles.ng string
72+
# ^ inline-styles.ng
73+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
74+
# ^^ inline-styles.ng
75+
> styles: [ '.example { width: 100px; }' ],
76+
#^^ inline-styles.ng
77+
# ^^^^^^ inline-styles.ng meta.object-literal.key.ts
78+
# ^ inline-styles.ng meta.object-literal.key.ts punctuation.separator.key-value.ts
79+
# ^ inline-styles.ng
80+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
81+
# ^ inline-styles.ng
82+
# ^ inline-styles.ng string
83+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng source.css
84+
# ^ inline-styles.ng string
85+
# ^ inline-styles.ng
86+
# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts
87+
# ^^ inline-styles.ng
88+
>
89+
>//// Parenthesization tests
90+
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng
91+
> styles: ( (( [ ( '.example { width: 100px; }' ) ] )) ),
92+
#^^ inline-styles.ng
93+
# ^^^^^^ inline-styles.ng meta.object-literal.key.ts
94+
# ^ inline-styles.ng meta.object-literal.key.ts punctuation.separator.key-value.ts
95+
# ^ inline-styles.ng
96+
# ^ inline-styles.ng meta.brace.round.ts
97+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng
98+
# ^ inline-styles.ng meta.brace.round.ts
99+
# ^^^^^^^ inline-styles.ng
100+
# ^^ inline-styles.ng
101+
>})
102+
#^^^ inline-styles.ng
103+
>export class TMComponent{}
104+
#^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng
105+
>

syntaxes/test/driver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// yarn test:syntaxes [options]
44
//
55
// Options:
6-
// -u, --update update snapshot files (always passes)
6+
// -u update snapshot files (always passes)
77

88
import 'jasmine';
99

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"comment": "Dummy HTML TextMate grammar for use in testing",
3+
"scopeName": "source.css"
4+
}

0 commit comments

Comments
 (0)