From b2d9a2618763e68e8c6509d9c42176b1dfbdfff5 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 8 Nov 2017 00:43:46 +0100 Subject: [PATCH 1/2] Conservative fix for tag names taking precedence over property names --- grammars/scss.cson | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/grammars/scss.cson b/grammars/scss.cson index 45497d6..5962012 100644 --- a/grammars/scss.cson +++ b/grammars/scss.cson @@ -973,8 +973,13 @@ 'properties': 'patterns': [ { - 'begin': '(? Date: Wed, 8 Nov 2017 01:05:54 +0100 Subject: [PATCH 2/2] Specs --- spec/scss-spec.coffee | 163 +++++++++++++++++++++++++++--------------- 1 file changed, 107 insertions(+), 56 deletions(-) diff --git a/spec/scss-spec.coffee b/spec/scss-spec.coffee index c438a20..c4c5eff 100644 --- a/spec/scss-spec.coffee +++ b/spec/scss-spec.coffee @@ -93,60 +93,60 @@ describe 'SCSS grammar', -> expect(tokens[4]).toEqual value: 'placeholder', scopes: ['source.css.scss', 'meta.at-rule.extend.scss', 'entity.other.attribute-name.placeholder.css'] expect(tokens[5]).toEqual value: ';', scopes: ['source.css.scss', 'punctuation.terminator.rule.css'] - describe "attribute selectors", -> - it "tokenizes them correctly", -> - {tokens} = grammar.tokenizeLine '[something="1"]' - - expect(tokens[0]).toEqual value: '[', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.begin.bracket.square.scss'] - expect(tokens[1]).toEqual value: 'something', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'entity.other.attribute-name.attribute.scss'] - expect(tokens[2]).toEqual value: '=', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'keyword.operator.scss'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.begin.scss'] - expect(tokens[4]).toEqual value: '1', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.end.scss'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.end.bracket.square.scss'] - - it "tokenizes complex attribute selectors", -> - {tokens} = grammar.tokenizeLine "[cla#\{$s}^=abc#\{d}e]" - - expect(tokens[0]).toEqual value: "[", scopes: ["source.css.scss", "meta.attribute-selector.scss", "punctuation.definition.attribute-selector.begin.bracket.square.scss"] - expect(tokens[1]).toEqual value: "cla", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss"] - expect(tokens[2]).toEqual value: "#\{", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss", "variable.interpolation.scss", "punctuation.definition.interpolation.begin.bracket.curly.scss"] - expect(tokens[3]).toEqual value: "$s", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss", "variable.interpolation.scss", "variable.scss"] - expect(tokens[4]).toEqual value: "}", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss", "variable.interpolation.scss", "punctuation.definition.interpolation.end.bracket.curly.scss"] - expect(tokens[5]).toEqual value: "^=", scopes: ["source.css.scss", "meta.attribute-selector.scss", "keyword.operator.scss"] - expect(tokens[6]).toEqual value: "abc", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss"] - expect(tokens[7]).toEqual value: "#\{", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss", "variable.interpolation.scss", "punctuation.definition.interpolation.begin.bracket.curly.scss"] - expect(tokens[8]).toEqual value: "d", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss", "variable.interpolation.scss"] - expect(tokens[9]).toEqual value: "}", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss", "variable.interpolation.scss", "punctuation.definition.interpolation.end.bracket.curly.scss"] - expect(tokens[10]).toEqual value: "e", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss"] - expect(tokens[11]).toEqual value: "]", scopes: ["source.css.scss", "meta.attribute-selector.scss", "punctuation.definition.attribute-selector.end.bracket.square.scss"] - - it "tokenizes the $= selector", -> - {tokens} = grammar.tokenizeLine "[class$=test]" - - expect(tokens[0]).toEqual value: "[", scopes: ["source.css.scss", "meta.attribute-selector.scss", "punctuation.definition.attribute-selector.begin.bracket.square.scss"] - expect(tokens[1]).toEqual value: "class", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss"] - expect(tokens[2]).toEqual value: "$=", scopes: ["source.css.scss", "meta.attribute-selector.scss", "keyword.operator.scss"] - expect(tokens[3]).toEqual value: "test", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss"] - expect(tokens[4]).toEqual value: "]", scopes: ["source.css.scss", "meta.attribute-selector.scss", "punctuation.definition.attribute-selector.end.bracket.square.scss"] - - it "tokenizes multiple attribute selectors", -> - {tokens} = grammar.tokenizeLine '[data-name="text-color"][data-value="null"]' - - expect(tokens[0]).toEqual value: '[', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.begin.bracket.square.scss'] - expect(tokens[1]).toEqual value: 'data-name', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'entity.other.attribute-name.attribute.scss'] - expect(tokens[2]).toEqual value: '=', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'keyword.operator.scss'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.begin.scss'] - expect(tokens[4]).toEqual value: 'text-color', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.end.scss'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.end.bracket.square.scss'] - expect(tokens[7]).toEqual value: '[', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.begin.bracket.square.scss'] - expect(tokens[8]).toEqual value: 'data-value', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'entity.other.attribute-name.attribute.scss'] - expect(tokens[9]).toEqual value: '=', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'keyword.operator.scss'] - expect(tokens[10]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.begin.scss'] - expect(tokens[11]).toEqual value: 'null', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss'] - expect(tokens[12]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.end.scss'] - expect(tokens[13]).toEqual value: ']', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.end.bracket.square.scss'] + describe "attribute selectors", -> + it "tokenizes them correctly", -> + {tokens} = grammar.tokenizeLine '[something="1"]' + + expect(tokens[0]).toEqual value: '[', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.begin.bracket.square.scss'] + expect(tokens[1]).toEqual value: 'something', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'entity.other.attribute-name.attribute.scss'] + expect(tokens[2]).toEqual value: '=', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'keyword.operator.scss'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.begin.scss'] + expect(tokens[4]).toEqual value: '1', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.end.scss'] + expect(tokens[6]).toEqual value: ']', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.end.bracket.square.scss'] + + it "tokenizes complex attribute selectors", -> + {tokens} = grammar.tokenizeLine "[cla#\{$s}^=abc#\{d}e]" + + expect(tokens[0]).toEqual value: "[", scopes: ["source.css.scss", "meta.attribute-selector.scss", "punctuation.definition.attribute-selector.begin.bracket.square.scss"] + expect(tokens[1]).toEqual value: "cla", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss"] + expect(tokens[2]).toEqual value: "#\{", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss", "variable.interpolation.scss", "punctuation.definition.interpolation.begin.bracket.curly.scss"] + expect(tokens[3]).toEqual value: "$s", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss", "variable.interpolation.scss", "variable.scss"] + expect(tokens[4]).toEqual value: "}", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss", "variable.interpolation.scss", "punctuation.definition.interpolation.end.bracket.curly.scss"] + expect(tokens[5]).toEqual value: "^=", scopes: ["source.css.scss", "meta.attribute-selector.scss", "keyword.operator.scss"] + expect(tokens[6]).toEqual value: "abc", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss"] + expect(tokens[7]).toEqual value: "#\{", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss", "variable.interpolation.scss", "punctuation.definition.interpolation.begin.bracket.curly.scss"] + expect(tokens[8]).toEqual value: "d", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss", "variable.interpolation.scss"] + expect(tokens[9]).toEqual value: "}", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss", "variable.interpolation.scss", "punctuation.definition.interpolation.end.bracket.curly.scss"] + expect(tokens[10]).toEqual value: "e", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss"] + expect(tokens[11]).toEqual value: "]", scopes: ["source.css.scss", "meta.attribute-selector.scss", "punctuation.definition.attribute-selector.end.bracket.square.scss"] + + it "tokenizes the $= selector", -> + {tokens} = grammar.tokenizeLine "[class$=test]" + + expect(tokens[0]).toEqual value: "[", scopes: ["source.css.scss", "meta.attribute-selector.scss", "punctuation.definition.attribute-selector.begin.bracket.square.scss"] + expect(tokens[1]).toEqual value: "class", scopes: ["source.css.scss", "meta.attribute-selector.scss", "entity.other.attribute-name.attribute.scss"] + expect(tokens[2]).toEqual value: "$=", scopes: ["source.css.scss", "meta.attribute-selector.scss", "keyword.operator.scss"] + expect(tokens[3]).toEqual value: "test", scopes: ["source.css.scss", "meta.attribute-selector.scss", "string.unquoted.attribute-value.scss"] + expect(tokens[4]).toEqual value: "]", scopes: ["source.css.scss", "meta.attribute-selector.scss", "punctuation.definition.attribute-selector.end.bracket.square.scss"] + + it "tokenizes multiple attribute selectors", -> + {tokens} = grammar.tokenizeLine '[data-name="text-color"][data-value="null"]' + + expect(tokens[0]).toEqual value: '[', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.begin.bracket.square.scss'] + expect(tokens[1]).toEqual value: 'data-name', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'entity.other.attribute-name.attribute.scss'] + expect(tokens[2]).toEqual value: '=', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'keyword.operator.scss'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.begin.scss'] + expect(tokens[4]).toEqual value: 'text-color', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.end.scss'] + expect(tokens[6]).toEqual value: ']', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.end.bracket.square.scss'] + expect(tokens[7]).toEqual value: '[', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.begin.bracket.square.scss'] + expect(tokens[8]).toEqual value: 'data-value', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'entity.other.attribute-name.attribute.scss'] + expect(tokens[9]).toEqual value: '=', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'keyword.operator.scss'] + expect(tokens[10]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.begin.scss'] + expect(tokens[11]).toEqual value: 'null', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss'] + expect(tokens[12]).toEqual value: '"', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'string.quoted.double.attribute-value.scss', 'punctuation.definition.string.end.scss'] + expect(tokens[13]).toEqual value: ']', scopes: ['source.css.scss', 'meta.attribute-selector.scss', 'punctuation.definition.attribute-selector.end.bracket.square.scss'] describe '@at-root', -> it 'tokenizes it correctly', -> @@ -314,7 +314,7 @@ describe 'SCSS grammar', -> expect(tokens[8]).toEqual value: ';', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.terminator.rule.scss'] expect(tokens[10]).toEqual value: '}', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.section.property-list.end.bracket.curly.scss'] - it 'tokenizes nested property-lists', -> + it 'tokenizes inline nested property-lists', -> {tokens} = grammar.tokenizeLine 'very-custom { very-very-custom { color: inherit; } margin: top; }' expect(tokens[2]).toEqual value: '{', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.section.property-list.begin.bracket.curly.scss'] @@ -328,6 +328,29 @@ describe 'SCSS grammar', -> expect(tokens[19]).toEqual value: 'top', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-value.scss', 'support.constant.property-value.css'] expect(tokens[22]).toEqual value: '}', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.section.property-list.end.bracket.curly.scss'] + it 'tokenizes multiline nested property-lists', -> + lines = grammar.tokenizeLines ''' + .test { + display: flex; + margin: 12px; + h3 + { + color: red; + } + } + ''' + + expect(lines[0][0]).toEqual value: '.', scopes: ['source.css.scss', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(lines[0][1]).toEqual value: 'test', scopes: ['source.css.scss', 'entity.other.attribute-name.class.css'] + expect(lines[0][3]).toEqual value: '{', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.section.property-list.begin.bracket.curly.scss'] + expect(lines[1][1]).toEqual value: 'display', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-name.scss', 'support.type.property-name.css'] + expect(lines[2][1]).toEqual value: 'margin', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-name.scss', 'support.type.property-name.css'] + expect(lines[3][1]).toEqual value: 'h3', scopes: ['source.css.scss', 'meta.property-list.scss', 'entity.name.tag.css'] + expect(lines[4][1]).toEqual value: '{', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'punctuation.section.property-list.begin.bracket.curly.scss'] + expect(lines[5][1]).toEqual value: 'color', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'meta.property-name.scss', 'support.type.property-name.css'] + expect(lines[6][1]).toEqual value: '}', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'punctuation.section.property-list.end.bracket.curly.scss'] + expect(lines[7][0]).toEqual value: '}', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.section.property-list.end.bracket.curly.scss'] + it 'tokenizes an incomplete inline property-list', -> {tokens} = grammar.tokenizeLine 'very-custom { color: inherit}' @@ -369,7 +392,7 @@ describe 'SCSS grammar', -> expect(tokens[32]).toEqual value: ')', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-value.scss', 'punctuation.definition.end.bracket.round.scss'] describe 'property names with a prefix that matches an element name', -> - it 'does not confuse them with properties', -> + it 'does not confuse them with selectors', -> tokens = grammar.tokenizeLines ''' text { text-align: center; @@ -396,6 +419,34 @@ describe 'SCSS grammar', -> expect(tokens[1][3]).toEqual value: ' ', scopes: ['source.css.scss', 'meta.property-list.scss'] expect(tokens[1][4]).toEqual value: 'fixed', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-value.scss', 'support.constant.property-value.css'] + describe 'property names that match element names', -> + it 'does not confuse them with selectors', -> + tokens = grammar.tokenizeLines ''' + content { + content: 'foo'; + cursor { + cursor: auto; + } + } + ''' + + expect(tokens[0][0]).toEqual value: 'content', scopes: ['source.css.scss', 'entity.name.tag.css'] + expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.section.property-list.begin.bracket.curly.scss'] + expect(tokens[1][1]).toEqual value: 'content', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-name.scss', 'support.type.property-name.css'] + expect(tokens[1][2]).toEqual value: ':', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.separator.key-value.scss'] + expect(tokens[1][4]).toEqual value: '\'', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-value.scss', 'string.quoted.single.scss', 'punctuation.definition.string.begin.scss'] + expect(tokens[1][5]).toEqual value: 'foo', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-value.scss', 'string.quoted.single.scss'] + expect(tokens[1][6]).toEqual value: '\'', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-value.scss', 'string.quoted.single.scss', 'punctuation.definition.string.end.scss'] + expect(tokens[1][7]).toEqual value: ';', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.terminator.rule.scss'] + expect(tokens[2][1]).toEqual value: 'cursor', scopes: ['source.css.scss', 'meta.property-list.scss', 'entity.name.tag.css'] + expect(tokens[2][3]).toEqual value: '{', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'punctuation.section.property-list.begin.bracket.curly.scss'] + expect(tokens[3][1]).toEqual value: 'cursor', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'meta.property-name.scss', 'support.type.property-name.css'] + expect(tokens[3][2]).toEqual value: ':', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'punctuation.separator.key-value.scss'] + expect(tokens[3][4]).toEqual value: 'auto', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'meta.property-value.scss', 'support.constant.property-value.css'] + expect(tokens[3][5]).toEqual value: ';', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'punctuation.terminator.rule.scss'] + expect(tokens[4][1]).toEqual value: '}', scopes: ['source.css.scss', 'meta.property-list.scss', 'meta.property-list.scss', 'punctuation.section.property-list.end.bracket.curly.scss'] + expect(tokens[5][0]).toEqual value: '}', scopes: ['source.css.scss', 'meta.property-list.scss', 'punctuation.section.property-list.end.bracket.curly.scss'] + describe 'vendor properties', -> it 'tokenizes the browser prefix', -> {tokens} = grammar.tokenizeLine 'body { -webkit-box-shadow: none; }'