Skip to content

Commit 38c45ef

Browse files
Fix invalid identifier check for nesting selector & and add nesting tests
1 parent 8af4189 commit 38c45ef

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

grammars/css.cson

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,8 @@
19491949
[!"'%(*;<?@^`|\\]}] # - NOTE: We exempt `)` from the list of checked
19501950
| # symbols to avoid matching `:not(.invalid)`
19511951
/ (?!\\*) # - Avoid invalidating the start of a comment
1952+
|
1953+
&(?=[-a-zA-Z_0-9]|[^\\x00-\\x7F]) # - & followed by an identifier is invalid
19521954
)+
19531955
)
19541956
# Mark remainder of selector invalid

spec/css-spec.mjs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,4 +3690,35 @@ describe('CSS grammar', function () {
36903690
assert.deepStrictEqual(tokens[0][11], { scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'], value: '}' });
36913691
});
36923692
});
3693+
3694+
describe('CSS Nesting', function () {
3695+
it('tokenizes the nesting selector &', function () {
3696+
var tokens;
3697+
tokens = testGrammar.tokenizeLine('& {}').tokens;
3698+
assert.deepStrictEqual(tokens[0], { scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.nesting.css'], value: '&' });
3699+
});
3700+
3701+
it('tokenizes the nesting selector & with class', function () {
3702+
var tokens;
3703+
tokens = testGrammar.tokenizeLine('&.foo {}').tokens;
3704+
assert.deepStrictEqual(tokens[0], { scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.nesting.css'], value: '&' });
3705+
assert.deepStrictEqual(tokens[1], { scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'], value: '.' });
3706+
assert.deepStrictEqual(tokens[2], { scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'], value: 'foo' });
3707+
});
3708+
3709+
it('tokenizes the nesting selector & with pseudo-class', function () {
3710+
var tokens;
3711+
tokens = testGrammar.tokenizeLine('&:hover {}').tokens;
3712+
assert.deepStrictEqual(tokens[0], { scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.nesting.css'], value: '&' });
3713+
assert.deepStrictEqual(tokens[1], { scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'], value: ':' });
3714+
assert.deepStrictEqual(tokens[2], { scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'], value: 'hover' });
3715+
});
3716+
3717+
it('tokenizes the nesting selector & inside a rule', function () {
3718+
var tokens;
3719+
tokens = testGrammar.tokenizeLine(' & > .bar {}').tokens;
3720+
assert.deepStrictEqual(tokens[1], { scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.nesting.css'], value: '&' });
3721+
assert.deepStrictEqual(tokens[3], { scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'], value: '>' });
3722+
});
3723+
});
36933724
});

0 commit comments

Comments
 (0)