From a7d07ab72cc45a8f52a002afcc72eb578b567e6d Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 17:50:50 -0700 Subject: [PATCH 01/18] Add some languages * language-c * language-clojure * language-coffee-script * language-csharp * language-css * language-gfm * language-git * language-go --- packages/language-c/spec/c-spec.js | 1291 ++++++ .../language-clojure/spec/clojure-spec.js | 513 +++ .../spec/coffee-script-literate-spec.js | 157 + .../spec/coffee-script-spec.js | 1630 +++++++ packages/language-csharp/spec/grammar-spec.js | 21 + packages/language-css/spec/css-spec.js | 3954 +++++++++++++++++ packages/language-gfm/spec/gfm-spec.js | 960 ++++ packages/language-git/spec/git-spec.js | 212 + packages/language-go/spec/go-spec.js | 1229 +++++ packages/language-go/spec/language-go-spec.js | 72 + 10 files changed, 10039 insertions(+) create mode 100644 packages/language-c/spec/c-spec.js create mode 100644 packages/language-clojure/spec/clojure-spec.js create mode 100644 packages/language-coffee-script/spec/coffee-script-literate-spec.js create mode 100644 packages/language-coffee-script/spec/coffee-script-spec.js create mode 100644 packages/language-csharp/spec/grammar-spec.js create mode 100644 packages/language-css/spec/css-spec.js create mode 100644 packages/language-gfm/spec/gfm-spec.js create mode 100644 packages/language-git/spec/git-spec.js create mode 100644 packages/language-go/spec/go-spec.js create mode 100644 packages/language-go/spec/language-go-spec.js diff --git a/packages/language-c/spec/c-spec.js b/packages/language-c/spec/c-spec.js new file mode 100644 index 0000000000..73b11e3a68 --- /dev/null +++ b/packages/language-c/spec/c-spec.js @@ -0,0 +1,1291 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +let TextEditor = null; +const buildTextEditor = function(params) { + if (atom.workspace.buildTextEditor != null) { + return atom.workspace.buildTextEditor(params); + } else { + if (TextEditor == null) { ({ + TextEditor + } = require('atom')); } + return new TextEditor(params); + } +}; + +describe("Language-C", function() { + let grammar = null; + + beforeEach(function() { + atom.config.set('core.useTreeSitterParsers', false); + + return waitsForPromise(() => atom.packages.activatePackage('language-c')); + }); + + describe("C", function() { + beforeEach(() => grammar = atom.grammars.grammarForScopeName('source.c')); + + it("parses the grammar", function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe('source.c'); + }); + + it("tokenizes punctuation", function() { + let {tokens} = grammar.tokenizeLine('hi;'); + expect(tokens[1]).toEqual({value: ';', scopes: ['source.c', 'punctuation.terminator.statement.c']}); + + ({tokens} = grammar.tokenizeLine('a[b]')); + expect(tokens[1]).toEqual({value: '[', scopes: ['source.c', 'punctuation.definition.begin.bracket.square.c']}); + expect(tokens[3]).toEqual({value: ']', scopes: ['source.c', 'punctuation.definition.end.bracket.square.c']}); + + ({tokens} = grammar.tokenizeLine('a, b')); + return expect(tokens[1]).toEqual({value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c']}); + }); + + it("tokenizes functions", function() { + const lines = grammar.tokenizeLines(`\ +int something(int param) { + return 0; +}\ +` + ); + expect(lines[0][0]).toEqual({value: 'int', scopes: ['source.c', 'storage.type.c']}); + expect(lines[0][2]).toEqual({value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(lines[0][3]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); + expect(lines[0][4]).toEqual({value: 'int', scopes: ['source.c', 'meta.function.c', 'storage.type.c']}); + expect(lines[0][6]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); + expect(lines[0][8]).toEqual({value: '{', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); + expect(lines[1][1]).toEqual({value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c']}); + expect(lines[1][3]).toEqual({value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c']}); + return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + }); + + it("tokenizes varargs ellipses", function() { + const {tokens} = grammar.tokenizeLine('void function(...);'); + expect(tokens[0]).toEqual({value: 'void', scopes: ['source.c', 'storage.type.c']}); + expect(tokens[2]).toEqual({value: 'function', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); + expect(tokens[4]).toEqual({value: '...', scopes: ['source.c', 'meta.function.c', 'punctuation.vararg-ellipses.c']}); + return expect(tokens[5]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); + }); + + it("tokenizes various _t types", function() { + let {tokens} = grammar.tokenizeLine('size_t var;'); + expect(tokens[0]).toEqual({value: 'size_t', scopes: ['source.c', 'support.type.sys-types.c']}); + + ({tokens} = grammar.tokenizeLine('pthread_t var;')); + expect(tokens[0]).toEqual({value: 'pthread_t', scopes: ['source.c', 'support.type.pthread.c']}); + + ({tokens} = grammar.tokenizeLine('int32_t var;')); + expect(tokens[0]).toEqual({value: 'int32_t', scopes: ['source.c', 'support.type.stdint.c']}); + + ({tokens} = grammar.tokenizeLine('myType_t var;')); + return expect(tokens[0]).toEqual({value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c']}); + }); + + it("tokenizes 'line continuation' character", function() { + const {tokens} = grammar.tokenizeLine("ma\\\nin(){};"); + expect(tokens[0]).toEqual({value: 'ma', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: '\\', scopes: ['source.c', 'constant.character.escape.line-continuation.c']}); + return expect(tokens[3]).toEqual({value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + }); + + describe("strings", () => it("tokenizes them", function() { + let tokens; + const delimsByScope = { + 'string.quoted.double.c': '"', + 'string.quoted.single.c': '\'' + }; + + for (let scope in delimsByScope) { + const delim = delimsByScope[scope]; + ({tokens} = grammar.tokenizeLine(delim + 'a' + delim)); + expect(tokens[0]).toEqual({value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c', scope]}); + expect(tokens[2]).toEqual({value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.end.c']}); + + ({tokens} = grammar.tokenizeLine(delim + 'a' + '\\' + '\n' + 'b' + delim)); + expect(tokens[0]).toEqual({value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c', scope]}); + expect(tokens[2]).toEqual({value: '\\', scopes: ['source.c', scope, 'constant.character.escape.line-continuation.c']}); + expect(tokens[4]).toEqual({value: 'b', scopes: ['source.c', scope]}); + expect(tokens[5]).toEqual({value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.end.c']}); + } + + ({tokens} = grammar.tokenizeLine('"%d"')); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: '%d', scopes: ['source.c', 'string.quoted.double.c', 'constant.other.placeholder.c']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + + ({tokens} = grammar.tokenizeLine('"%"')); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: '%', scopes: ['source.c', 'string.quoted.double.c', 'invalid.illegal.placeholder.c']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + + ({tokens} = grammar.tokenizeLine('"%" PRId32')); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: '%', scopes: ['source.c', 'string.quoted.double.c']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + + ({tokens} = grammar.tokenizeLine('"%" SCNd32')); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: '%', scopes: ['source.c', 'string.quoted.double.c']}); + return expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + })); + + describe("comments", () => it("tokenizes them", function() { + let {tokens} = grammar.tokenizeLine('/**/'); + expect(tokens[0]).toEqual({value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c']}); + expect(tokens[1]).toEqual({value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c']}); + + ({tokens} = grammar.tokenizeLine('/* foo */')); + expect(tokens[0]).toEqual({value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c']}); + expect(tokens[1]).toEqual({value: ' foo ', scopes: ['source.c', 'comment.block.c']}); + expect(tokens[2]).toEqual({value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c']}); + + ({tokens} = grammar.tokenizeLine('*/*')); + return expect(tokens[0]).toEqual({value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c']}); + })); + + describe("preprocessor directives", function() { + it("tokenizes '#line'", function() { + const {tokens} = grammar.tokenizeLine('#line 151 "copy.c"'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.line.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'line', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.line.c']}); + expect(tokens[3]).toEqual({value: '151', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[6]).toEqual({value: 'copy.c', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c']}); + return expect(tokens[7]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + }); + + it("tokenizes '#undef'", function() { + const {tokens} = grammar.tokenizeLine('#undef FOO'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'undef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.c']}); + return expect(tokens[3]).toEqual({value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + }); + + it("tokenizes '#pragma'", function() { + let {tokens} = grammar.tokenizeLine('#pragma once'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'pragma', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.pragma.c']}); + expect(tokens[3]).toEqual({value: 'once', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c']}); + + ({tokens} = grammar.tokenizeLine('#pragma clang diagnostic ignored "-Wunused-variable"')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'pragma', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.pragma.c']}); + expect(tokens[3]).toEqual({value: 'clang', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c']}); + expect(tokens[5]).toEqual({value: 'diagnostic', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c']}); + expect(tokens[7]).toEqual({value: 'ignored', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c']}); + expect(tokens[10]).toEqual({value: '-Wunused-variable', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'string.quoted.double.c']}); + + ({tokens} = grammar.tokenizeLine('#pragma mark – Initialization')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'pragma mark', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c']}); + return expect(tokens[3]).toEqual({value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c']}); + }); + + describe("define", function() { + it("tokenizes '#define [identifier name]'", function() { + const {tokens} = grammar.tokenizeLine('#define _FILE_NAME_H_'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + return expect(tokens[3]).toEqual({value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + }); + + it("tokenizes '#define [identifier name] [value]'", function() { + let {tokens} = grammar.tokenizeLine('#define WIDTH 80'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(tokens[3]).toEqual({value: 'WIDTH', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[5]).toEqual({value: '80', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); + + ({tokens} = grammar.tokenizeLine('#define ABC XYZ(1)')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(tokens[3]).toEqual({value: 'ABC', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[4]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[5]).toEqual({value: 'XYZ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'entity.name.function.c']}); + expect(tokens[6]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'punctuation.section.arguments.begin.bracket.round.c']}); + expect(tokens[7]).toEqual({value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'constant.numeric.c']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c']}); + + ({tokens} = grammar.tokenizeLine('#define PI_PLUS_ONE (3.14 + 1)')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(tokens[3]).toEqual({value: 'PI_PLUS_ONE', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[4]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[5]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(tokens[6]).toEqual({value: '3.14', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); + expect(tokens[8]).toEqual({value: '+', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c']}); + expect(tokens[10]).toEqual({value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); + return expect(tokens[11]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + }); + + return describe("macros", function() { + it("tokenizes them", function() { + let {tokens} = grammar.tokenizeLine('#define INCREMENT(x) x++'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(tokens[3]).toEqual({value: 'INCREMENT', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c']}); + expect(tokens[5]).toEqual({value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c']}); + expect(tokens[6]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c']}); + expect(tokens[7]).toEqual({value: ' x', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[8]).toEqual({value: '++', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.increment.c']}); + + ({tokens} = grammar.tokenizeLine('#define MULT(x, y) (x) * (y)')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(tokens[3]).toEqual({value: 'MULT', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c']}); + expect(tokens[5]).toEqual({value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c']}); + expect(tokens[6]).toEqual({value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c']}); + expect(tokens[7]).toEqual({value: ' y', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c']}); + expect(tokens[9]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[10]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(tokens[11]).toEqual({value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[12]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(tokens[13]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[14]).toEqual({value: '*', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c']}); + expect(tokens[15]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[16]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(tokens[17]).toEqual({value: 'y', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[18]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + + ({tokens} = grammar.tokenizeLine('#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while ( 0 )')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(tokens[3]).toEqual({value: 'SWAP', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c']}); + expect(tokens[5]).toEqual({value: 'a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c']}); + expect(tokens[6]).toEqual({value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c']}); + expect(tokens[7]).toEqual({value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c']}); + expect(tokens[10]).toEqual({value: 'do', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.c']}); + expect(tokens[12]).toEqual({value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); + expect(tokens[13]).toEqual({value: ' a ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c']}); + expect(tokens[14]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); + expect(tokens[15]).toEqual({value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c']}); + expect(tokens[16]).toEqual({value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c']}); + expect(tokens[17]).toEqual({value: ' b ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c']}); + expect(tokens[18]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); + expect(tokens[19]).toEqual({value: ' a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c']}); + expect(tokens[20]).toEqual({value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c']}); + expect(tokens[21]).toEqual({value: ' a ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c']}); + expect(tokens[22]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); + expect(tokens[23]).toEqual({value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c']}); + expect(tokens[24]).toEqual({value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c']}); + expect(tokens[25]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c']}); + expect(tokens[26]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(tokens[28]).toEqual({value: 'while', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.c']}); + expect(tokens[29]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + expect(tokens[30]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(tokens[32]).toEqual({value: '0', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); + return expect(tokens[34]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + }); + + it("tokenizes multiline macros", function() { + let lines = grammar.tokenizeLines(`\ +#define max(a,b) (a>b)? \\ + a:b\ +` + ); + expect(lines[0][17]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.character.escape.line-continuation.c']}); + expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.preprocessor.macro.c']}); + + lines = grammar.tokenizeLines(`\ +#define SWAP(a, b) { \\ + a ^= b; \\ + b ^= a; \\ + a ^= b; \\ +}\ +` + ); + expect(lines[0][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(lines[0][1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(lines[0][3]).toEqual({value: 'SWAP', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(lines[0][4]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c']}); + expect(lines[0][5]).toEqual({value: 'a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c']}); + expect(lines[0][6]).toEqual({value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c']}); + expect(lines[0][7]).toEqual({value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c']}); + expect(lines[0][8]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c']}); + expect(lines[0][10]).toEqual({value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); + expect(lines[0][12]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); + expect(lines[1][1]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); + expect(lines[1][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); + expect(lines[2][1]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); + expect(lines[2][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); + expect(lines[3][1]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); + expect(lines[3][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); + return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + }); + + return it("tokenizes complex definitions", function() { + const lines = grammar.tokenizeLines(`\ +#define MakeHook(name) struct HOOK name = {{false, 0L}, \\ +((HOOKF)(*HookEnt)), ID("hook")}\ +` + ); + expect(lines[0][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(lines[0][1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(lines[0][3]).toEqual({value: 'MakeHook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(lines[0][4]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c']}); + expect(lines[0][5]).toEqual({value: 'name', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c']}); + expect(lines[0][6]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c']}); + expect(lines[0][8]).toEqual({value: 'struct', scopes: ['source.c', 'meta.preprocessor.macro.c', 'storage.type.c']}); + expect(lines[0][10]).toEqual({value: '=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.assignment.c']}); + expect(lines[0][12]).toEqual({value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); + expect(lines[0][13]).toEqual({value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); + expect(lines[0][14]).toEqual({value: 'false', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.language.c']}); + expect(lines[0][15]).toEqual({value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c']}); + expect(lines[0][17]).toEqual({value: '0L', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.numeric.c']}); + expect(lines[0][18]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(lines[0][19]).toEqual({value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c']}); + expect(lines[0][21]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); + expect(lines[1][0]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(lines[1][1]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(lines[1][3]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(lines[1][4]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(lines[1][5]).toEqual({value: '*', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.c']}); + expect(lines[1][7]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(lines[1][8]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(lines[1][9]).toEqual({value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c']}); + expect(lines[1][11]).toEqual({value: 'ID', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'entity.name.function.c']}); + expect(lines[1][12]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.begin.bracket.round.c']}); + expect(lines[1][13]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.begin.c"]}); + expect(lines[1][14]).toEqual({value: 'hook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c']}); + expect(lines[1][15]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.end.c"]}); + expect(lines[1][16]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c']}); + return expect(lines[1][17]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + }); + }); + }); + + describe("includes", function() { + it("tokenizes '#include'", function() { + let {tokens} = grammar.tokenizeLine('#include '); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); + expect(tokens[3]).toEqual({value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[4]).toEqual({value: 'stdio.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c']}); + expect(tokens[5]).toEqual({value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c']}); + + ({tokens} = grammar.tokenizeLine('#include')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); + expect(tokens[2]).toEqual({value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[3]).toEqual({value: 'stdio.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c']}); + expect(tokens[4]).toEqual({value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c']}); + + ({tokens} = grammar.tokenizeLine('#include_')); + expect(tokens[0]).toEqual({value: '#include_', scopes: ['source.c']}); + + ({tokens} = grammar.tokenizeLine('#include "file"')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); + expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[4]).toEqual({value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); + return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + }); + + it("tokenizes '#import'", function() { + const {tokens} = grammar.tokenizeLine('#import "file"'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c']}); + expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[4]).toEqual({value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); + return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + }); + + return it("tokenizes '#include_next'", function() { + const {tokens} = grammar.tokenizeLine('#include_next "next.h"'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'include_next', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c']}); + expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[4]).toEqual({value: 'next.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); + return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + }); + }); + + describe("diagnostics", function() { + it("tokenizes '#error'", function() { + const {tokens} = grammar.tokenizeLine('#error "C++ compiler required."'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'error', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c']}); + return expect(tokens[4]).toEqual({value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); + }); + + return it("tokenizes '#warning'", function() { + const {tokens} = grammar.tokenizeLine('#warning "This is a warning."'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c', 'punctuation.definition.directive.c']}); + expect(tokens[1]).toEqual({value: 'warning', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c']}); + return expect(tokens[4]).toEqual({value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); + }); + }); + + return describe("conditionals", function() { + it("tokenizes if-elif-else preprocessor blocks", function() { + const lines = grammar.tokenizeLines(`\ +#if defined(CREDIT) + credit(); +#elif defined(DEBIT) + debit(); +#else + printerror(); +#endif\ +` + ); + expect(lines[0][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[0][1]).toEqual({value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[0][3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[0][5]).toEqual({value: 'CREDIT', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[1][1]).toEqual({value: 'credit', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(lines[1][2]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); + expect(lines[1][3]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); + expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[2][1]).toEqual({value: 'elif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][5]).toEqual({value: 'DEBIT', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[3][1]).toEqual({value: 'debit', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(lines[3][2]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); + expect(lines[3][3]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); + expect(lines[4][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[4][1]).toEqual({value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[5][1]).toEqual({value: 'printerror', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(lines[5][2]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); + expect(lines[5][3]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); + expect(lines[6][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + return expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + }); + + it("tokenizes if-true-else blocks", function() { + const lines = grammar.tokenizeLines(`\ +#if 1 +int something() { + #if 1 + return 1; + #else + return 0; + #endif +} +#else +int something() { + return 0; +} +#endif\ +` + ); + expect(lines[0][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[0][1]).toEqual({value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[0][3]).toEqual({value: '1', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); + expect(lines[1][0]).toEqual({value: 'int', scopes: ['source.c', 'storage.type.c']}); + expect(lines[1][2]).toEqual({value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(lines[2][1]).toEqual({value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[2][2]).toEqual({value: 'if', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][4]).toEqual({value: '1', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'constant.numeric.c']}); + expect(lines[3][1]).toEqual({value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c']}); + expect(lines[3][3]).toEqual({value: '1', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c']}); + expect(lines[4][1]).toEqual({value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[4][2]).toEqual({value: 'else', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[5][0]).toEqual({value: ' return 0;', scopes: ['source.c', 'meta.block.c', 'comment.block.preprocessor.else-branch.in-block.c']}); + expect(lines[6][1]).toEqual({value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[6][2]).toEqual({value: 'endif', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[8][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[8][1]).toEqual({value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[9][0]).toEqual({value: 'int something() {', scopes: ['source.c', 'comment.block.preprocessor.else-branch.c']}); + expect(lines[12][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + return expect(lines[12][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + }); + + it("tokenizes if-false-else blocks", function() { + let lines = grammar.tokenizeLines(`\ +int something() { + #if 0 + return 1; + #else + return 0; + #endif +}\ +` + ); + expect(lines[0][0]).toEqual({value: 'int', scopes: ['source.c', 'storage.type.c']}); + expect(lines[0][2]).toEqual({value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(lines[1][1]).toEqual({value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[1][2]).toEqual({value: 'if', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[1][4]).toEqual({value: '0', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'constant.numeric.c']}); + expect(lines[2][0]).toEqual({value: ' return 1;', scopes: ['source.c', 'meta.block.c', 'comment.block.preprocessor.if-branch.in-block.c']}); + expect(lines[3][1]).toEqual({value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[3][2]).toEqual({value: 'else', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[4][1]).toEqual({value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c']}); + expect(lines[4][3]).toEqual({value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c']}); + expect(lines[5][1]).toEqual({value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[5][2]).toEqual({value: 'endif', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + + lines = grammar.tokenizeLines(`\ +#if 0 + something(); +#endif\ +` + ); + expect(lines[0][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[0][1]).toEqual({value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[0][3]).toEqual({value: '0', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); + expect(lines[1][0]).toEqual({value: ' something();', scopes: ['source.c', 'comment.block.preprocessor.if-branch.c']}); + expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + return expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + }); + + it("tokenizes ifdef-elif blocks", function() { + const lines = grammar.tokenizeLines(`\ +#ifdef __unix__ /* is defined by compilers targeting Unix systems */ + # include +#elif defined _WIN32 /* is defined by compilers targeting Windows systems */ + # include +#endif\ +` + ); + expect(lines[0][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[0][1]).toEqual({value: 'ifdef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[0][3]).toEqual({value: '__unix__', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[0][5]).toEqual({value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c']}); + expect(lines[0][6]).toEqual({value: ' is defined by compilers targeting Unix systems ', scopes: ['source.c', 'comment.block.c']}); + expect(lines[0][7]).toEqual({value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c']}); + expect(lines[1][1]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c']}); + expect(lines[1][2]).toEqual({value: ' include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); + expect(lines[1][4]).toEqual({value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c']}); + expect(lines[1][5]).toEqual({value: 'unistd.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c']}); + expect(lines[1][6]).toEqual({value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c']}); + expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[2][1]).toEqual({value: 'elif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][5]).toEqual({value: '_WIN32', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[2][7]).toEqual({value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c']}); + expect(lines[2][8]).toEqual({value: ' is defined by compilers targeting Windows systems ', scopes: ['source.c', 'comment.block.c']}); + expect(lines[2][9]).toEqual({value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c']}); + expect(lines[3][1]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c']}); + expect(lines[3][2]).toEqual({value: ' include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); + expect(lines[3][4]).toEqual({value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c']}); + expect(lines[3][5]).toEqual({value: 'windows.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c']}); + expect(lines[3][6]).toEqual({value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c']}); + expect(lines[4][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + return expect(lines[4][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + }); + + it("tokenizes ifndef blocks", function() { + const lines = grammar.tokenizeLines(`\ +#ifndef _INCL_GUARD + #define _INCL_GUARD +#endif\ +` + ); + expect(lines[0][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[0][1]).toEqual({value: 'ifndef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[0][3]).toEqual({value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[1][1]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); + expect(lines[1][2]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); + expect(lines[1][4]).toEqual({value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + return expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + }); + + it("highlights stray elif, else and endif usages as invalid", function() { + const lines = grammar.tokenizeLines(`\ +#if defined SOMEMACRO +#else +#elif //elif not permitted here +#endif +#else //else without if +#endif //endif without if\ +` + ); + expect(lines[2][0]).toEqual({value: '#elif', scopes: ['source.c', 'invalid.illegal.stray-elif.c']}); + expect(lines[4][0]).toEqual({value: '#else', scopes: ['source.c', 'invalid.illegal.stray-else.c']}); + return expect(lines[5][0]).toEqual({value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c']}); + }); + + it("highlights errorneous defined usage as invalid", function() { + const {tokens} = grammar.tokenizeLine('#if defined == VALUE'); + return expect(tokens[3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c']}); + }); + + it("tokenizes multi line conditional queries", function() { + const lines = grammar.tokenizeLines(`\ +#if !defined (MACRO_A) \\ + || !defined MACRO_C + #define MACRO_A TRUE +#elif MACRO_C == (5 + 4 - /* multi line comment */ \\ + SOMEMACRO(TRUE) * 8) // single line comment +#endif\ +` + ); + expect(lines[0][2]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.c']}); + expect(lines[0][3]).toEqual({value: '!', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c']}); + expect(lines[0][7]).toEqual({value: 'MACRO_A', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[0][10]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.c', 'constant.character.escape.line-continuation.c']}); + expect(lines[1][1]).toEqual({value: '||', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c']}); + expect(lines[1][3]).toEqual({value: '!', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c']}); + expect(lines[1][4]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[1][6]).toEqual({value: 'MACRO_C', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[3][2]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.c']}); + expect(lines[3][3]).toEqual({value: 'MACRO_C', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[3][5]).toEqual({value: '==', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.comparison.c']}); + expect(lines[3][7]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(lines[3][8]).toEqual({value: '5', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); + expect(lines[3][10]).toEqual({value: '+', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c']}); + expect(lines[3][14]).toEqual({value: '-', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c']}); + expect(lines[3][16]).toEqual({value: '/*', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c', 'punctuation.definition.comment.begin.c']}); + expect(lines[3][17]).toEqual({value: ' multi line comment ', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c']}); + expect(lines[3][18]).toEqual({value: '*/', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c', 'punctuation.definition.comment.end.c']}); + expect(lines[3][20]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.c', 'constant.character.escape.line-continuation.c']}); + expect(lines[4][1]).toEqual({value: 'SOMEMACRO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[4][3]).toEqual({value: 'TRUE', scopes: ['source.c', 'meta.preprocessor.c', 'constant.language.c']}); + expect(lines[4][6]).toEqual({value: '*', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c']}); + expect(lines[4][9]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(lines[4][11]).toEqual({value: '//', scopes: ['source.c', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); + return expect(lines[4][12]).toEqual({value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp']}); + }); + + return it("tokenizes ternary operator usage in preprocessor conditionals", function() { + const {tokens} = grammar.tokenizeLine('#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)'); + expect(tokens[9]).toEqual({value: '?', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); + expect(tokens[11]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + return expect(tokens[17]).toEqual({value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); + }); + }); + }); + + describe("indentation", function() { + let editor = null; + + beforeEach(function() { + editor = buildTextEditor(); + return editor.setGrammar(grammar); + }); + + const expectPreservedIndentation = function(text) { + editor.setText(text); + editor.autoIndentBufferRows(0, editor.getLineCount() - 1); + + const expectedLines = text.split('\n'); + const actualLines = editor.getText().split('\n'); + return Array.from(actualLines).map((actualLine, i) => + expect([ + actualLine, + editor.indentLevelForLine(actualLine) + ]).toEqual([ + expectedLines[i], + editor.indentLevelForLine(expectedLines[i]) + ])); + }; + + it("indents allman-style curly braces", () => expectPreservedIndentation(`\ +if (a) +{ +for (;;) +{ + do + { + while (b) + { + c(); + } + } + while (d) +} +}\ +` + )); + + it("indents non-allman-style curly braces", () => expectPreservedIndentation(`\ +if (a) { +for (;;) { + do { + while (b) { + c(); + } + } while (d) +} +}\ +` + )); + + it("indents function arguments", () => expectPreservedIndentation(`\ +a( +b, +c( + d +) +);\ +` + )); + + it("indents array and struct literals", () => expectPreservedIndentation(`\ +some_t a[3] = { +{ .b = c }, +{ .b = c, .d = {1, 2} }, +};\ +` + )); + + return it("tokenizes binary literal", function() { + const {tokens} = grammar.tokenizeLine('0b101010'); + return expect(tokens[0]).toEqual({value: '0b101010', scopes: ['source.c', 'constant.numeric.c']}); + }); + }); + + describe("access", function() { + it("tokenizes the dot access operator", function() { + let lines = grammar.tokenizeLines(`\ +{ + a. +}\ +` + ); + expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.block.c']}); + expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a.b; +}\ +` + ); + expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.block.c']}); + expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); + expect(lines[1][2]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a.b() +}\ +` + ); + expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.block.c']}); + expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); + expect(lines[1][2]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'meta.function-call.c', 'entity.name.function.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a. b; +}\ +` + ); + expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); + expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a .b; +}\ +` + ); + expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); + expect(lines[1][2]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a . b; +}\ +` + ); + expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); + return expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + }); + + return it("tokenizes the pointer access operator", function() { + let lines = grammar.tokenizeLines(`\ +{ + a->b; +}\ +` + ); + expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + expect(lines[1][2]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a->b() +}\ +` + ); + expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.block.c']}); + expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a-> b; +}\ +` + ); + expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a ->b; +}\ +` + ); + expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + expect(lines[1][2]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a -> b; +}\ +` + ); + expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + + lines = grammar.tokenizeLines(`\ +{ + a-> +}\ +` + ); + expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.block.c']}); + return expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + }); + }); + + return describe("operators", function() { + it("tokenizes the sizeof operator", function() { + let {tokens} = grammar.tokenizeLine('sizeof unary_expression'); + expect(tokens[0]).toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); + expect(tokens[1]).toEqual({value: ' unary_expression', scopes: ['source.c']}); + + ({tokens} = grammar.tokenizeLine('sizeof (int)')); + expect(tokens[0]).toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); + expect(tokens[1]).toEqual({value: ' ', scopes: ['source.c']}); + expect(tokens[2]).toEqual({value: '(', scopes: ['source.c', 'punctuation.section.parens.begin.bracket.round.c']}); + expect(tokens[3]).toEqual({value: 'int', scopes: ['source.c', 'storage.type.c']}); + expect(tokens[4]).toEqual({value: ')', scopes: ['source.c', 'punctuation.section.parens.end.bracket.round.c']}); + + ({tokens} = grammar.tokenizeLine('$sizeof')); + expect(tokens[1]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); + + ({tokens} = grammar.tokenizeLine('sizeof$')); + expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); + + ({tokens} = grammar.tokenizeLine('sizeof_')); + return expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); + }); + + it("tokenizes the increment operator", function() { + let {tokens} = grammar.tokenizeLine('i++'); + expect(tokens[0]).toEqual({value: 'i', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: '++', scopes: ['source.c', 'keyword.operator.increment.c']}); + + ({tokens} = grammar.tokenizeLine('++i')); + expect(tokens[0]).toEqual({value: '++', scopes: ['source.c', 'keyword.operator.increment.c']}); + return expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); + }); + + it("tokenizes the decrement operator", function() { + let {tokens} = grammar.tokenizeLine('i--'); + expect(tokens[0]).toEqual({value: 'i', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: '--', scopes: ['source.c', 'keyword.operator.decrement.c']}); + + ({tokens} = grammar.tokenizeLine('--i')); + expect(tokens[0]).toEqual({value: '--', scopes: ['source.c', 'keyword.operator.decrement.c']}); + return expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); + }); + + it("tokenizes logical operators", function() { + let {tokens} = grammar.tokenizeLine('!a'); + expect(tokens[0]).toEqual({value: '!', scopes: ['source.c', 'keyword.operator.logical.c']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c']}); + + const operators = ['&&', '||']; + return (() => { + const result = []; + for (let operator of Array.from(operators)) { + ({tokens} = grammar.tokenizeLine('a ' + operator + ' b')); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: operator, scopes: ['source.c', 'keyword.operator.logical.c']}); + result.push(expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']})); + } + return result; + })(); + }); + + it("tokenizes comparison operators", function() { + const operators = ['<=', '>=', '!=', '==', '<', '>' ]; + + return (() => { + const result = []; + for (let operator of Array.from(operators)) { + const {tokens} = grammar.tokenizeLine('a ' + operator + ' b'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: operator, scopes: ['source.c', 'keyword.operator.comparison.c']}); + result.push(expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']})); + } + return result; + })(); + }); + + it("tokenizes arithmetic operators", function() { + const operators = ['+', '-', '*', '/', '%']; + + return (() => { + const result = []; + for (let operator of Array.from(operators)) { + const {tokens} = grammar.tokenizeLine('a ' + operator + ' b'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: operator, scopes: ['source.c', 'keyword.operator.c']}); + result.push(expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']})); + } + return result; + })(); + }); + + it("tokenizes ternary operators", function() { + const {tokens} = grammar.tokenizeLine('a ? b : c'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: '?', scopes: ['source.c', 'keyword.operator.ternary.c']}); + expect(tokens[2]).toEqual({value: ' b ', scopes: ['source.c']}); + expect(tokens[3]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); + return expect(tokens[4]).toEqual({value: ' c', scopes: ['source.c']}); + }); + + it("tokenizes ternary operators with member access", function() { + const {tokens} = grammar.tokenizeLine('a ? b.c : d'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: '?', scopes: ['source.c', 'keyword.operator.ternary.c']}); + expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); + expect(tokens[3]).toEqual({value: '.', scopes: ['source.c', 'punctuation.separator.dot-access.c']}); + expect(tokens[4]).toEqual({value: 'c', scopes: ['source.c', 'variable.other.member.c']}); + expect(tokens[5]).toEqual({value: ' ', scopes: ['source.c']}); + expect(tokens[6]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); + return expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); + }); + + it("tokenizes ternary operators with pointer dereferencing", function() { + const {tokens} = grammar.tokenizeLine('a ? b->c : d'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: '?', scopes: ['source.c', 'keyword.operator.ternary.c']}); + expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); + expect(tokens[3]).toEqual({value: '->', scopes: ['source.c', 'punctuation.separator.pointer-access.c']}); + expect(tokens[4]).toEqual({value: 'c', scopes: ['source.c', 'variable.other.member.c']}); + expect(tokens[5]).toEqual({value: ' ', scopes: ['source.c']}); + expect(tokens[6]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); + return expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); + }); + + it("tokenizes ternary operators with function invocation", function() { + const {tokens} = grammar.tokenizeLine('a ? f(b) : c'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: '?', scopes: ['source.c', 'keyword.operator.ternary.c']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.c']}); + expect(tokens[3]).toEqual({value: 'f', scopes: ['source.c', 'meta.function-call.c', 'entity.name.function.c']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.begin.bracket.round.c']}); + expect(tokens[5]).toEqual({value: 'b', scopes: ['source.c', 'meta.function-call.c']}); + expect(tokens[6]).toEqual({value: ')', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.end.bracket.round.c']}); + expect(tokens[7]).toEqual({value: ' ', scopes: ['source.c']}); + expect(tokens[8]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); + return expect(tokens[9]).toEqual({value: ' c', scopes: ['source.c']}); + }); + + describe("bitwise", function() { + it("tokenizes bitwise 'not'", function() { + const {tokens} = grammar.tokenizeLine('~a'); + expect(tokens[0]).toEqual({value: '~', scopes: ['source.c', 'keyword.operator.c']}); + return expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c']}); + }); + + it("tokenizes shift operators", function() { + let {tokens} = grammar.tokenizeLine('>>'); + expect(tokens[0]).toEqual({value: '>>', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); + + ({tokens} = grammar.tokenizeLine('<<')); + return expect(tokens[0]).toEqual({value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); + }); + + return it("tokenizes them", function() { + const operators = ['|', '^', '&']; + + return (() => { + const result = []; + for (let operator of Array.from(operators)) { + const {tokens} = grammar.tokenizeLine('a ' + operator + ' b'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: operator, scopes: ['source.c', 'keyword.operator.c']}); + result.push(expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']})); + } + return result; + })(); + }); + }); + + return describe("assignment", function() { + it("tokenizes the assignment operator", function() { + const {tokens} = grammar.tokenizeLine('a = b'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: '=', scopes: ['source.c', 'keyword.operator.assignment.c']}); + return expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); + }); + + it("tokenizes compound assignment operators", function() { + const operators = ['+=', '-=', '*=', '/=', '%=']; + return (() => { + const result = []; + for (let operator of Array.from(operators)) { + const {tokens} = grammar.tokenizeLine('a ' + operator + ' b'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: operator, scopes: ['source.c', 'keyword.operator.assignment.compound.c']}); + result.push(expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']})); + } + return result; + })(); + }); + + return it("tokenizes bitwise compound operators", function() { + const operators = ['<<=', '>>=', '&=', '^=', '|=']; + return (() => { + const result = []; + for (let operator of Array.from(operators)) { + const {tokens} = grammar.tokenizeLine('a ' + operator + ' b'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: operator, scopes: ['source.c', 'keyword.operator.assignment.compound.bitwise.c']}); + result.push(expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']})); + } + return result; + })(); + }); + }); + }); +}); + + return describe("C++", function() { + beforeEach(() => grammar = atom.grammars.grammarForScopeName('source.cpp')); + + it("parses the grammar", function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe('source.cpp'); + }); + + it("tokenizes this with `.this` class", function() { + const {tokens} = grammar.tokenizeLine('this.x'); + return expect(tokens[0]).toEqual({value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp']}); + }); + + it("tokenizes classes", function() { + const lines = grammar.tokenizeLines(`\ +class Thing { + int x; +}\ +` + ); + expect(lines[0][0]).toEqual({value: 'class', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'storage.type.cpp']}); + return expect(lines[0][2]).toEqual({value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp']}); + }); + + it("tokenizes 'extern C'", function() { + let lines = grammar.tokenizeLines(`\ +extern "C" { +#include "legacy_C_header.h" +}\ +` + ); + expect(lines[0][0]).toEqual({value: 'extern', scopes: ['source.cpp', 'meta.extern-block.cpp', 'storage.modifier.cpp']}); + expect(lines[0][2]).toEqual({value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(lines[0][3]).toEqual({value: 'C', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp']}); + expect(lines[0][4]).toEqual({value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + expect(lines[0][6]).toEqual({value: '{', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.begin.bracket.curly.c']}); + expect(lines[1][0]).toEqual({value: '#', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c']}); + expect(lines[1][1]).toEqual({value: 'include', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); + expect(lines[1][3]).toEqual({value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); + expect(lines[1][4]).toEqual({value: 'legacy_C_header.h', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); + expect(lines[1][5]).toEqual({value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + expect(lines[2][0]).toEqual({value: '}', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.end.bracket.curly.c']}); + + lines = grammar.tokenizeLines(`\ +#ifdef __cplusplus +extern "C" { +#endif + // legacy C code here +#ifdef __cplusplus +} +#endif\ +` + ); + expect(lines[0][0]).toEqual({value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[0][1]).toEqual({value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[0][3]).toEqual({value: '__cplusplus', scopes: ['source.cpp', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(lines[1][0]).toEqual({value: 'extern', scopes: ['source.cpp', 'meta.extern-block.cpp', 'storage.modifier.cpp']}); + expect(lines[1][2]).toEqual({value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(lines[1][3]).toEqual({value: 'C', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp']}); + expect(lines[1][4]).toEqual({value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + expect(lines[1][6]).toEqual({value: '{', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.begin.bracket.curly.c']}); + expect(lines[2][0]).toEqual({value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[3][1]).toEqual({value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); + expect(lines[3][2]).toEqual({value: ' legacy C code here', scopes: ['source.cpp', 'comment.line.double-slash.cpp']}); + expect(lines[4][0]).toEqual({value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + expect(lines[4][1]).toEqual({value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[5][0]).toEqual({value: '}', scopes: ['source.cpp']}); + expect(lines[6][0]).toEqual({value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); + return expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + }); + + it("tokenizes UTF string escapes", function() { + const lines = grammar.tokenizeLines(`\ +string str = U"\\U01234567\\u0123\\"\\0123\\x123";\ +` + ); + expect(lines[0][0]).toEqual({value: 'string str ', scopes: ['source.cpp']}); + expect(lines[0][1]).toEqual({value: '=', scopes: ['source.cpp', 'keyword.operator.assignment.c']}); + expect(lines[0][3]).toEqual({value: 'U', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp', 'meta.encoding.cpp']}); + expect(lines[0][4]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(lines[0][5]).toEqual({value: '\\U01234567', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp']}); + expect(lines[0][6]).toEqual({value: '\\u0123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp']}); + expect(lines[0][7]).toEqual({value: '\\"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp']}); + expect(lines[0][8]).toEqual({value: '\\012', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp']}); + expect(lines[0][9]).toEqual({value: '3', scopes: ['source.cpp', 'string.quoted.double.cpp']}); + expect(lines[0][10]).toEqual({value: '\\x123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp']}); + expect(lines[0][11]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + return expect(lines[0][12]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + }); + + it("tokenizes % format specifiers", function() { + let {tokens} = grammar.tokenizeLine('"%d"'); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(tokens[1]).toEqual({value: '%d', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.other.placeholder.c']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + + ({tokens} = grammar.tokenizeLine('"%"')); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(tokens[1]).toEqual({value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp', 'invalid.illegal.placeholder.c']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + + ({tokens} = grammar.tokenizeLine('"%" PRId32')); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(tokens[1]).toEqual({value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp']}); + return expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + }); + + it("tokenizes raw string literals", function() { + const lines = grammar.tokenizeLines(`\ +string str = R"test( + this is \"a\" test 'string' +)test";\ +` + ); + expect(lines[0][0]).toEqual({value: 'string str ', scopes: ['source.cpp']}); + expect(lines[0][3]).toEqual({value: 'R"test(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(lines[1][0]).toEqual({value: ' this is "a" test \'string\'', scopes: ['source.cpp', 'string.quoted.double.raw.cpp']}); + expect(lines[2][0]).toEqual({value: ')test"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); + return expect(lines[2][1]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + }); + + it("errors on long raw string delimiters", function() { + const lines = grammar.tokenizeLines(`\ +string str = R"01234567890123456()01234567890123456";\ +` + ); + expect(lines[0][0]).toEqual({value: 'string str ', scopes: ['source.cpp']}); + expect(lines[0][3]).toEqual({value: 'R"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(lines[0][4]).toEqual({value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp', 'invalid.illegal.delimiter-too-long.cpp']}); + expect(lines[0][5]).toEqual({value: '(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp']}); + expect(lines[0][6]).toEqual({value: ')', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); + expect(lines[0][7]).toEqual({value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp', 'invalid.illegal.delimiter-too-long.cpp']}); + expect(lines[0][8]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); + return expect(lines[0][9]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + }); + + it("tokenizes destructors", function() { + let {tokens} = grammar.tokenizeLine('~Foo() {}'); + expect(tokens[0]).toEqual({value: '~Foo', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'entity.name.function.cpp']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c']}); + expect(tokens[2]).toEqual({value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c']}); + expect(tokens[4]).toEqual({value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + + ({tokens} = grammar.tokenizeLine('Foo::~Bar() {}')); + expect(tokens[0]).toEqual({value: 'Foo::~Bar', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'entity.name.function.cpp']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c']}); + expect(tokens[2]).toEqual({value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c']}); + expect(tokens[4]).toEqual({value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); + return expect(tokens[5]).toEqual({value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + }); + + describe("digit separators", function() { + it("recognizes numbers with digit separators", function() { + let {tokens} = grammar.tokenizeLine("1'000"); + expect(tokens[0]).toEqual({value: "1'000", scopes: ['source.cpp', 'constant.numeric.c']}); + + ({tokens} = grammar.tokenizeLine("123'456.500'000e-1'5")); + expect(tokens[0]).toEqual({value: "123'456.500'000e-1'5", scopes: ['source.cpp', 'constant.numeric.c']}); + + ({tokens} = grammar.tokenizeLine("0x1234'5678")); + expect(tokens[0]).toEqual({value: "0x1234'5678", scopes: ['source.cpp', 'constant.numeric.c']}); + + ({tokens} = grammar.tokenizeLine("0'123'456")); + expect(tokens[0]).toEqual({value: "0'123'456", scopes: ['source.cpp', 'constant.numeric.c']}); + + ({tokens} = grammar.tokenizeLine("0b1100'0011'1111'0000")); + return expect(tokens[0]).toEqual({value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c']}); + }); + + return it("does not tokenize single quotes at the beginning or end of numbers as digit separators", function() { + let {tokens} = grammar.tokenizeLine("'1000"); + expect(tokens[0]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: "1000", scopes: ['source.cpp', 'string.quoted.single.c']}); + + ({tokens} = grammar.tokenizeLine("1000'")); + expect(tokens[0]).toEqual({value: "1000", scopes: ['source.cpp', 'constant.numeric.c']}); + return expect(tokens[1]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); + }); + }); + + describe("comments", () => it("tokenizes them", function() { + const {tokens} = grammar.tokenizeLine('// comment'); + expect(tokens[0]).toEqual({value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); + expect(tokens[1]).toEqual({value: ' comment', scopes: ['source.cpp', 'comment.line.double-slash.cpp']}); + + let lines = grammar.tokenizeLines(`\ +// separated\\ +comment\ +` + ); + expect(lines[0][0]).toEqual({value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); + expect(lines[0][1]).toEqual({value: ' separated', scopes: ['source.cpp', 'comment.line.double-slash.cpp']}); + expect(lines[0][2]).toEqual({value: '\\', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'constant.character.escape.line-continuation.c']}); + expect(lines[1][0]).toEqual({value: 'comment', scopes: ['source.cpp', 'comment.line.double-slash.cpp']}); + + lines = grammar.tokenizeLines(`\ +// The space character \x20 is used to prevent stripping trailing whitespace +// not separated\\\x20 +comment\ +` + ); + expect(lines[1][0]).toEqual({value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); + expect(lines[1][1]).toEqual({value: ' not separated\\ ', scopes: ['source.cpp', 'comment.line.double-slash.cpp']}); + return expect(lines[2][0]).toEqual({value: 'comment', scopes: ['source.cpp']}); + })); + + return describe("operators", () => it("tokenizes ternary operators with namespace resolution", function() { + const {tokens} = grammar.tokenizeLine('a ? ns::b : ns::c'); + expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.cpp']}); + expect(tokens[1]).toEqual({value: '?', scopes: ['source.cpp', 'keyword.operator.ternary.c']}); + expect(tokens[2]).toEqual({value: ' ns', scopes: ['source.cpp']}); + expect(tokens[3]).toEqual({value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp']}); + expect(tokens[4]).toEqual({value: 'b ', scopes: ['source.cpp']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.cpp', 'keyword.operator.ternary.c']}); + expect(tokens[6]).toEqual({value: ' ns', scopes: ['source.cpp']}); + expect(tokens[7]).toEqual({value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp']}); + return expect(tokens[8]).toEqual({value: 'c', scopes: ['source.cpp']}); + })); +}); +}); diff --git a/packages/language-clojure/spec/clojure-spec.js b/packages/language-clojure/spec/clojure-spec.js new file mode 100644 index 0000000000..2dc1309089 --- /dev/null +++ b/packages/language-clojure/spec/clojure-spec.js @@ -0,0 +1,513 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS201: Simplify complex destructure assignments + * DS205: Consider reworking code to avoid use of IIFEs + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +describe("Clojure grammar", function() { + let grammar = null; + + beforeEach(function() { + atom.config.set('core.useTreeSitterParsers', false); + atom.config.set('core.useExperimentalModernTreeSitter', false); + + waitsForPromise(() => atom.packages.activatePackage("language-clojure")); + + return runs(() => grammar = atom.grammars.grammarForScopeName("source.clojure")); + }); + + it("parses the grammar", function() { + expect(grammar).toBeDefined(); + return expect(grammar.scopeName).toBe("source.clojure"); + }); + + it("tokenizes semicolon comments", function() { + const {tokens} = grammar.tokenizeLine("; clojure"); + expect(tokens[0]).toEqual({value: ";", scopes: ["source.clojure", "comment.line.semicolon.clojure", "punctuation.definition.comment.clojure"]}); + return expect(tokens[1]).toEqual({value: " clojure", scopes: ["source.clojure", "comment.line.semicolon.clojure"]}); +}); + + it("does not tokenize escaped semicolons as comments", function() { + const {tokens} = grammar.tokenizeLine("\\; clojure"); + expect(tokens[0]).toEqual({value: "\\; ", scopes: ["source.clojure"]}); + return expect(tokens[1]).toEqual({value: "clojure", scopes: ["source.clojure", "meta.symbol.clojure"]}); +}); + + it("tokenizes shebang comments", function() { + const {tokens} = grammar.tokenizeLine("#!/usr/bin/env clojure"); + expect(tokens[0]).toEqual({value: "#!", scopes: ["source.clojure", "comment.line.shebang.clojure", "punctuation.definition.comment.shebang.clojure"]}); + return expect(tokens[1]).toEqual({value: "/usr/bin/env clojure", scopes: ["source.clojure", "comment.line.shebang.clojure"]}); +}); + + it("tokenizes strings", function() { + const {tokens} = grammar.tokenizeLine('"foo bar"'); + expect(tokens[0]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.begin.clojure"]}); + expect(tokens[1]).toEqual({value: 'foo bar', scopes: ["source.clojure", "string.quoted.double.clojure"]}); + return expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.end.clojure"]}); +}); + + it("tokenizes character escape sequences", function() { + const {tokens} = grammar.tokenizeLine('"\\n"'); + expect(tokens[0]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.begin.clojure"]}); + expect(tokens[1]).toEqual({value: '\\n', scopes: ["source.clojure", "string.quoted.double.clojure", "constant.character.escape.clojure"]}); + return expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.end.clojure"]}); +}); + + it("tokenizes regexes", function() { + const {tokens} = grammar.tokenizeLine('#"foo"'); + expect(tokens[0]).toEqual({value: '#"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.begin.clojure"]}); + expect(tokens[1]).toEqual({value: 'foo', scopes: ["source.clojure", "string.regexp.clojure"]}); + return expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.end.clojure"]}); +}); + + it("tokenizes backslash escape character in regexes", function() { + const {tokens} = grammar.tokenizeLine('#"\\\\" "/"'); + expect(tokens[0]).toEqual({value: '#"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.begin.clojure"]}); + expect(tokens[1]).toEqual({value: "\\\\", scopes: ['source.clojure', 'string.regexp.clojure', 'constant.character.escape.clojure']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.clojure', 'string.regexp.clojure', "punctuation.definition.regexp.end.clojure"]}); + expect(tokens[4]).toEqual({value: '"', scopes: ['source.clojure', 'string.quoted.double.clojure', 'punctuation.definition.string.begin.clojure']}); + expect(tokens[5]).toEqual({value: "/", scopes: ['source.clojure', 'string.quoted.double.clojure']}); + return expect(tokens[6]).toEqual({value: '"', scopes: ['source.clojure', 'string.quoted.double.clojure', 'punctuation.definition.string.end.clojure']}); +}); + + it("tokenizes escaped double quote in regexes", function() { + const {tokens} = grammar.tokenizeLine('#"\\""'); + expect(tokens[0]).toEqual({value: '#"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.begin.clojure"]}); + expect(tokens[1]).toEqual({value: '\\"', scopes: ['source.clojure', 'string.regexp.clojure', 'constant.character.escape.clojure']}); + return expect(tokens[2]).toEqual({value: '"', scopes: ['source.clojure', 'string.regexp.clojure', "punctuation.definition.regexp.end.clojure"]}); +}); + + it("tokenizes numerics", function() { + const numbers = { + "constant.numeric.ratio.clojure": ["1/2", "123/456", "+0/2", "-23/1"], + "constant.numeric.arbitrary-radix.clojure": ["2R1011", "16rDEADBEEF", "16rDEADBEEFN", "36rZebra"], + "constant.numeric.hexadecimal.clojure": ["0xDEADBEEF", "0XDEADBEEF", "0xDEADBEEFN", "0x0"], + "constant.numeric.octal.clojure": ["0123", "0123N", "00"], + "constant.numeric.double.clojure": ["123.45", "123.45e6", "123.45E6", "123.456M", "42.", "42.M", "42E+9M", "42E-0", "0M", "+0M", "42.E-23M"], + "constant.numeric.long.clojure": ["123", "12321", "123N", "+123N", "-123", "0"], + "constant.numeric.symbol.clojure": ["##Inf", "##-Inf", "##NaN"] + }; + + return (() => { + const result = []; + for (var scope in numbers) { + var nums = numbers[scope]; + result.push((() => { + const result1 = []; + for (let num of Array.from(nums)) { + const {tokens} = grammar.tokenizeLine(num); + result1.push(expect(tokens[0]).toEqual({value: num, scopes: ["source.clojure", scope]})); + } + return result1; + })()); + } + return result; + })(); +}); + + it("tokenizes booleans", function() { + const booleans = + {"constant.language.boolean.clojure": ["true", "false"]}; + + return (() => { + const result = []; + for (var scope in booleans) { + var bools = booleans[scope]; + result.push((() => { + const result1 = []; + for (let bool of Array.from(bools)) { + const {tokens} = grammar.tokenizeLine(bool); + result1.push(expect(tokens[0]).toEqual({value: bool, scopes: ["source.clojure", scope]})); + } + return result1; + })()); + } + return result; + })(); +}); + + it("tokenizes nil", function() { + const {tokens} = grammar.tokenizeLine("nil"); + return expect(tokens[0]).toEqual({value: "nil", scopes: ["source.clojure", "constant.language.nil.clojure"]}); +}); + + it("tokenizes keywords", function() { + let tokens; + const tests = { + "meta.expression.clojure": ["(:foo)"], + "meta.map.clojure": ["{:foo}"], + "meta.vector.clojure": ["[:foo]"], + "meta.quoted-expression.clojure": ["'(:foo)", "`(:foo)"] + }; + + for (let metaScope in tests) { + const lines = tests[metaScope]; + for (let line of Array.from(lines)) { + ({tokens} = grammar.tokenizeLine(line)); + expect(tokens[1]).toEqual({value: ":foo", scopes: ["source.clojure", metaScope, "constant.keyword.clojure"]}); + } + } + + ({tokens} = grammar.tokenizeLine("(def foo :bar)")); + expect(tokens[5]).toEqual({value: ":bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "constant.keyword.clojure"]}); + + // keywords can start with an uppercase non-ASCII letter + ({tokens} = grammar.tokenizeLine("(def foo :Öπ)")); + return expect(tokens[5]).toEqual({value: ":Öπ", scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "constant.keyword.clojure"]}); +}); + + it("tokenizes keyfns (keyword control)", function() { + const keyfns = ["declare", "declare-", "ns", "in-ns", "import", "use", "require", "load", "compile", "def", "defn", "defn-", "defmacro", "defåπç"]; + + return (() => { + const result = []; + for (let keyfn of Array.from(keyfns)) { + const {tokens} = grammar.tokenizeLine(`(${keyfn})`); + result.push(expect(tokens[1]).toEqual({value: keyfn, scopes: ["source.clojure", "meta.expression.clojure", "keyword.control.clojure"]})); + } + return result; + })(); +}); + + it("tokenizes keyfns (storage control)", function() { + const keyfns = ["if", "when", "for", "cond", "do", "let", "binding", "loop", "recur", "fn", "throw", "try", "catch", "finally", "case"]; + + return (() => { + const result = []; + for (let keyfn of Array.from(keyfns)) { + const {tokens} = grammar.tokenizeLine(`(${keyfn})`); + result.push(expect(tokens[1]).toEqual({value: keyfn, scopes: ["source.clojure", "meta.expression.clojure", "storage.control.clojure"]})); + } + return result; + })(); +}); + + it("tokenizes global definitions", function() { + const macros = ["ns", "declare", "def", "defn", "defn-", "defroutes", "compojure/defroutes", "rum.core/defc123-", "some.nested-ns/def-nested->symbol!?*", "def+!.?abc8:<>", "ns/def+!.?abc8:<>", "ns/defåÄÖπç"]; + + return (() => { + const result = []; + for (let macro of Array.from(macros)) { + const {tokens} = grammar.tokenizeLine(`(${macro} foo 'bar)`); + expect(tokens[1]).toEqual({value: macro, scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "keyword.control.clojure"]}); + result.push(expect(tokens[3]).toEqual({value: "foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "entity.global.clojure"]})); + } + return result; + })(); +}); + + it("tokenizes dynamic variables", function() { + const mutables = ["*ns*", "*foo-bar*", "*åÄÖπç*"]; + + return (() => { + const result = []; + for (let mutable of Array.from(mutables)) { + const {tokens} = grammar.tokenizeLine(mutable); + result.push(expect(tokens[0]).toEqual({value: mutable, scopes: ["source.clojure", "meta.symbol.dynamic.clojure"]})); + } + return result; + })(); +}); + + it("tokenizes metadata", function() { + let {tokens} = grammar.tokenizeLine("^Foo"); + expect(tokens[0]).toEqual({value: "^", scopes: ["source.clojure", "meta.metadata.simple.clojure"]}); + expect(tokens[1]).toEqual({value: "Foo", scopes: ["source.clojure", "meta.metadata.simple.clojure", "meta.symbol.clojure"]}); + + // non-ASCII letters + ({tokens} = grammar.tokenizeLine("^Öπ")); + expect(tokens[0]).toEqual({value: "^", scopes: ["source.clojure", "meta.metadata.simple.clojure"]}); + expect(tokens[1]).toEqual({value: "Öπ", scopes: ["source.clojure", "meta.metadata.simple.clojure", "meta.symbol.clojure"]}); + + ({tokens} = grammar.tokenizeLine("^{:foo true}")); + expect(tokens[0]).toEqual({value: "^{", scopes: ["source.clojure", "meta.metadata.map.clojure", "punctuation.section.metadata.map.begin.clojure"]}); + expect(tokens[1]).toEqual({value: ":foo", scopes: ["source.clojure", "meta.metadata.map.clojure", "constant.keyword.clojure"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.clojure", "meta.metadata.map.clojure"]}); + expect(tokens[3]).toEqual({value: "true", scopes: ["source.clojure", "meta.metadata.map.clojure", "constant.language.boolean.clojure"]}); + return expect(tokens[4]).toEqual({value: "}", scopes: ["source.clojure", "meta.metadata.map.clojure", "punctuation.section.metadata.map.end.trailing.clojure"]}); +}); + + it("tokenizes functions", function() { + let tokens; + const expressions = ["(foo)", "(foo 1 10)"]; + + for (let expr of Array.from(expressions)) { + ({tokens} = grammar.tokenizeLine(expr)); + expect(tokens[1]).toEqual({value: "foo", scopes: ["source.clojure", "meta.expression.clojure", "entity.name.function.clojure"]}); + } + + //non-ASCII letters + ({tokens} = grammar.tokenizeLine("(Öπ 2 20)")); + return expect(tokens[1]).toEqual({value: "Öπ", scopes: ["source.clojure", "meta.expression.clojure", "entity.name.function.clojure"]}); +}); + + it("tokenizes vars", function() { + let {tokens} = grammar.tokenizeLine("(func #'foo)"); + expect(tokens[2]).toEqual({value: " #", scopes: ["source.clojure", "meta.expression.clojure"]}); + expect(tokens[3]).toEqual({value: "'foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.var.clojure"]}); + + // non-ASCII letters + ({tokens} = grammar.tokenizeLine("(func #'Öπ)")); + expect(tokens[2]).toEqual({value: " #", scopes: ["source.clojure", "meta.expression.clojure"]}); + return expect(tokens[3]).toEqual({value: "'Öπ", scopes: ["source.clojure", "meta.expression.clojure", "meta.var.clojure"]}); +}); + + it("tokenizes symbols", function() { + let {tokens} = grammar.tokenizeLine("x"); + expect(tokens[0]).toEqual({value: "x", scopes: ["source.clojure", "meta.symbol.clojure"]}); + + // non-ASCII letters + ({tokens} = grammar.tokenizeLine("Öπ")); + expect(tokens[0]).toEqual({value: "Öπ", scopes: ["source.clojure", "meta.symbol.clojure"]}); + + // Should not be tokenized as a symbol + ({tokens} = grammar.tokenizeLine("1foobar")); + return expect(tokens[0]).toEqual({value: "1", scopes: ["source.clojure", "constant.numeric.long.clojure"]}); +}); + + it("tokenizes namespaces", function() { + let {tokens} = grammar.tokenizeLine("foo/bar"); + expect(tokens[0]).toEqual({value: "foo", scopes: ["source.clojure", "meta.symbol.namespace.clojure"]}); + expect(tokens[1]).toEqual({value: "/", scopes: ["source.clojure"]}); + expect(tokens[2]).toEqual({value: "bar", scopes: ["source.clojure", "meta.symbol.clojure"]}); + + // non-ASCII letters + ({tokens} = grammar.tokenizeLine("Öπ/Åä")); + expect(tokens[0]).toEqual({value: "Öπ", scopes: ["source.clojure", "meta.symbol.namespace.clojure"]}); + expect(tokens[1]).toEqual({value: "/", scopes: ["source.clojure"]}); + return expect(tokens[2]).toEqual({value: "Åä", scopes: ["source.clojure", "meta.symbol.clojure"]}); +}); + + const testMetaSection = function(metaScope, puncScope, startsWith, endsWith) { + // Entire expression on one line. + let adjustedLength1, adjustedLength2, after, token; + let {tokens} = grammar.tokenizeLine(`${startsWith}foo, bar${endsWith}`); + + let start = tokens[0], adjustedLength = Math.max(tokens.length, 2), mid = tokens.slice(1, adjustedLength - 1), end = tokens[adjustedLength - 1]; + + expect(start).toEqual({value: startsWith, scopes: ["source.clojure", `meta.${metaScope}.clojure`, `punctuation.section.${puncScope}.begin.clojure`]}); + expect(end).toEqual({value: endsWith, scopes: ["source.clojure", `meta.${metaScope}.clojure`, `punctuation.section.${puncScope}.end.trailing.clojure`]}); + + for (token of Array.from(mid)) { + expect(token.scopes.slice(0, 2)).toEqual(["source.clojure", `meta.${metaScope}.clojure`]); + } + + // Expression broken over multiple lines. + tokens = grammar.tokenizeLines(`${startsWith}foo\n bar${endsWith}`); + + start = tokens[0][0], + adjustedLength1 = Math.max(tokens[0].length, 2), + mid = tokens[0].slice(1, adjustedLength1 - 1), + after = tokens[0][adjustedLength1 - 1]; + + expect(start).toEqual({value: startsWith, scopes: ["source.clojure", `meta.${metaScope}.clojure`, `punctuation.section.${puncScope}.begin.clojure`]}); + + for (token of Array.from(mid)) { + expect(token.scopes.slice(0, 2)).toEqual(["source.clojure", `meta.${metaScope}.clojure`]); + } + + adjustedLength2 = Math.max(tokens[1].length, 1), + mid = tokens[1].slice(0, adjustedLength2 - 1), + end = tokens[1][adjustedLength2 - 1]; + + expect(end).toEqual({value: endsWith, scopes: ["source.clojure", `meta.${metaScope}.clojure`, `punctuation.section.${puncScope}.end.trailing.clojure`]}); + + return (() => { + const result = []; + for (token of Array.from(mid)) { + result.push(expect(token.scopes.slice(0, 2)).toEqual(["source.clojure", `meta.${metaScope}.clojure`])); + } + return result; + })(); + }; + + it("tokenizes expressions", () => testMetaSection("expression", "expression", "(", ")")); + + it("tokenizes quoted expressions", function() { + testMetaSection("quoted-expression", "expression", "'(", ")"); + return testMetaSection("quoted-expression", "expression", "`(", ")"); + }); + + it("tokenizes vectors", () => testMetaSection("vector", "vector", "[", "]")); + + it("tokenizes maps", () => testMetaSection("map", "map", "{", "}")); + + it("tokenizes sets", () => testMetaSection("set", "set", "\#{", "}")); + + it("tokenizes functions in nested sexp", function() { + const {tokens} = grammar.tokenizeLine("((foo bar) baz)"); + expect(tokens[0]).toEqual({value: "(", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.begin.clojure"]}); + expect(tokens[1]).toEqual({value: "(", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "punctuation.section.expression.begin.clojure"]}); + expect(tokens[2]).toEqual({value: "foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "entity.name.function.clojure"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure"]}); + expect(tokens[4]).toEqual({value: "bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "meta.symbol.clojure"]}); + expect(tokens[5]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "punctuation.section.expression.end.clojure"]}); + expect(tokens[6]).toEqual({value: " ", scopes: ["source.clojure", "meta.expression.clojure"]}); + expect(tokens[7]).toEqual({value: "baz", scopes: ["source.clojure", "meta.expression.clojure", "meta.symbol.clojure"]}); + return expect(tokens[8]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); +}); + + it("tokenizes maps used as functions", function() { + const {tokens} = grammar.tokenizeLine("({:foo bar} :foo)"); + expect(tokens[0]).toEqual({value: "(", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.begin.clojure"]}); + expect(tokens[1]).toEqual({value: "{", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "punctuation.section.map.begin.clojure"]}); + expect(tokens[2]).toEqual({value: ":foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "constant.keyword.clojure"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure"]}); + expect(tokens[4]).toEqual({value: "bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "meta.symbol.clojure"]}); + expect(tokens[5]).toEqual({value: "}", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "punctuation.section.map.end.clojure"]}); + expect(tokens[6]).toEqual({value: " ", scopes: ["source.clojure", "meta.expression.clojure"]}); + expect(tokens[7]).toEqual({value: ":foo", scopes: ["source.clojure", "meta.expression.clojure", "constant.keyword.clojure"]}); + return expect(tokens[8]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); +}); + + it("tokenizes sets used in functions", function() { + const {tokens} = grammar.tokenizeLine("(\#{:foo :bar})"); + expect(tokens[0]).toEqual({value: "(", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.begin.clojure"]}); + expect(tokens[1]).toEqual({value: "\#{", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "punctuation.section.set.begin.clojure"]}); + expect(tokens[2]).toEqual({value: ":foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "constant.keyword.clojure"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure"]}); + expect(tokens[4]).toEqual({value: ":bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "constant.keyword.clojure"]}); + expect(tokens[5]).toEqual({value: "}", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "punctuation.section.set.end.trailing.clojure"]}); + return expect(tokens[6]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); +}); + + return describe("firstLineMatch", function() { + it("recognises interpreter directives", function() { + let line; + const valid = `\ +#!/usr/sbin/boot foo +#!/usr/bin/boot foo=bar/ +#!/usr/sbin/boot +#!/usr/sbin/boot foo bar baz +#!/usr/bin/boot perl +#!/usr/bin/boot bin/perl +#!/usr/bin/boot +#!/bin/boot +#!/usr/bin/boot --script=usr/bin +#! /usr/bin/env A=003 B=149 C=150 D=xzd E=base64 F=tar G=gz H=head I=tail boot +#!\t/usr/bin/env --foo=bar boot --quu=quux +#! /usr/bin/boot +#!/usr/bin/env boot\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +\x20#!/usr/sbin/boot +\t#!/usr/sbin/boot +#!/usr/bin/env-boot/node-env/ +#!/usr/bin/das-boot +#! /usr/binboot +#!\t/usr/bin/env --boot=bar\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + + it("recognises Emacs modelines", function() { + let line; + const valid = `\ +#-*- Clojure -*- +#-*- mode: ClojureScript -*- +/* -*-clojureScript-*- */ +// -*- Clojure -*- +/* -*- mode:Clojure -*- */ +// -*- font:bar;mode:Clojure -*- +// -*- font:bar;mode:Clojure;foo:bar; -*- +// -*-font:mode;mode:Clojure-*- +// -*- foo:bar mode: clojureSCRIPT bar:baz -*- +" -*-foo:bar;mode:clojure;bar:foo-*- "; +" -*-font-mode:foo;mode:clojure;foo-bar:quux-*-" +"-*-font:x;foo:bar; mode : clojure; bar:foo;foooooo:baaaaar;fo:ba;-*-"; +"-*- font:x;foo : bar ; mode : ClojureScript ; bar : foo ; foooooo:baaaaar;fo:ba-*-";\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +/* --*clojure-*- */ +/* -*-- clojure -*- +/* -*- -- Clojure -*- +/* -*- Clojure -;- -*- +// -*- iClojure -*- +// -*- Clojure; -*- +// -*- clojure-door -*- +/* -*- model:clojure -*- +/* -*- indent-mode:clojure -*- +// -*- font:mode;Clojure -*- +// -*- mode: -*- Clojure +// -*- mode: das-clojure -*- +// -*-font:mode;mode:clojure--*-\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + + return it("recognises Vim modelines", function() { + let line; + const valid = `\ +vim: se filetype=clojure: +# vim: se ft=clojure: +# vim: set ft=Clojure: +# vim: set filetype=Clojure: +# vim: ft=Clojure +# vim: syntax=Clojure +# vim: se syntax=Clojure: +# ex: syntax=Clojure +# vim:ft=clojure +# vim600: ft=clojure +# vim>600: set ft=clojure: +# vi:noai:sw=3 ts=6 ft=clojure +# vi::::::::::noai:::::::::::: ft=clojure +# vim:ts=4:sts=4:sw=4:noexpandtab:ft=clojure +# vi:: noai : : : : sw =3 ts =6 ft =clojure +# vim: ts=4: pi sts=4: ft=clojure: noexpandtab: sw=4: +# vim: ts=4 sts=4: ft=clojure noexpandtab: +# vim:noexpandtab sts=4 ft=clojure ts=4 +# vim:noexpandtab:ft=clojure +# vim:ts=4:sts=4 ft=clojure:noexpandtab:\x20 +# vim:noexpandtab titlestring=hi\|there\\\\ ft=clojure ts=4\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +ex: se filetype=clojure: +_vi: se filetype=clojure: + vi: se filetype=clojure +# vim set ft=klojure +# vim: soft=clojure +# vim: clean-syntax=clojure: +# vim set ft=clojure: +# vim: setft=clojure: +# vim: se ft=clojure backupdir=tmp +# vim: set ft=clojure set cmdheight=1 +# vim:noexpandtab sts:4 ft:clojure ts:4 +# vim:noexpandtab titlestring=hi\\|there\\ ft=clojure ts=4 +# vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=clojure ts=4\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + }); +}); diff --git a/packages/language-coffee-script/spec/coffee-script-literate-spec.js b/packages/language-coffee-script/spec/coffee-script-literate-spec.js new file mode 100644 index 0000000000..b86aa34fb3 --- /dev/null +++ b/packages/language-coffee-script/spec/coffee-script-literate-spec.js @@ -0,0 +1,157 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +describe("CoffeeScript (Literate) grammar", function() { + let grammar = null; + + beforeEach(function() { + waitsForPromise(() => atom.packages.activatePackage("language-coffee-script")); + + return runs(() => grammar = atom.grammars.grammarForScopeName("source.litcoffee")); + }); + + it("parses the grammar", function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe("source.litcoffee"); + }); + + it("recognizes a code block after a list", function() { + const tokens = grammar.tokenizeLines(`\ +1. Example +2. List + + 1 + 2\ +` + ); + return expect(tokens[3][1]).toEqual({value: "1", scopes: ["source.litcoffee", "markup.raw.block.markdown", "constant.numeric.decimal.coffee"]}); +}); + + return describe("firstLineMatch", function() { + it("recognises interpreter directives", function() { + let line; + const valid = `\ +#!/usr/local/bin/coffee --no-header --literate -w +#!/usr/local/bin/coffee -l +#!/usr/local/bin/env coffee --literate -w\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +#!/usr/local/bin/coffee --no-head -literate -w +#!/usr/local/bin/coffee --wl +#!/usr/local/bin/env coffee --illiterate -w=l\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + + it("recognises Emacs modelines", function() { + let line; + const valid = `\ +#-*- litcoffee -*- +#-*- mode: litcoffee -*- +/* -*-litcoffee-*- */ +// -*- litcoffee -*- +/* -*- mode:LITCOFFEE -*- */ +// -*- font:bar;mode:LitCoffee -*- +// -*- font:bar;mode:litcoffee;foo:bar; -*- +// -*-font:mode;mode:litcoffee-*- +// -*- foo:bar mode: litcoffee bar:baz -*- +" -*-foo:bar;mode:litcoffee;bar:foo-*- "; +" -*-font-mode:foo;mode:LITcofFEE;foo-bar:quux-*-" +"-*-font:x;foo:bar; mode : litCOFFEE; bar:foo;foooooo:baaaaar;fo:ba;-*-"; +"-*- font:x;foo : bar ; mode : LiTcOFFEe ; bar : foo ; foooooo:baaaaar;fo:ba-*-";\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +/* --*litcoffee-*- */ +/* -*-- litcoffee -*- +/* -*- -- litcoffee -*- +/* -*- LITCOFFEE -;- -*- +// -*- itsLitCoffeeFam -*- +// -*- litcoffee; -*- +// -*- litcoffee-stuff -*- +/* -*- model:litcoffee -*- +/* -*- indent-mode:litcoffee -*- +// -*- font:mode;litcoffee -*- +// -*- mode: -*- litcoffee +// -*- mode: burnt-because-litcoffee -*- +// -*-font:mode;mode:litcoffee--*-\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + + return it("recognises Vim modelines", function() { + let line; + const valid = `\ +vim: se filetype=litcoffee: +# vim: se ft=litcoffee: +# vim: set ft=LITCOFFEE: +# vim: set filetype=litcoffee: +# vim: ft=LITCOFFEE +# vim: syntax=litcoffee +# vim: se syntax=litcoffee: +# ex: syntax=litcoffee +# vim:ft=LitCoffee +# vim600: ft=litcoffee +# vim>600: set ft=litcoffee: +# vi:noai:sw=3 ts=6 ft=litcoffee +# vi::::::::::noai:::::::::::: ft=litcoffee +# vim:ts=4:sts=4:sw=4:noexpandtab:ft=LITCOFFEE +# vi:: noai : : : : sw =3 ts =6 ft =litCoffee +# vim: ts=4: pi sts=4: ft=litcoffee: noexpandtab: sw=4: +# vim: ts=4 sts=4: ft=litcoffee noexpandtab: +# vim:noexpandtab sts=4 ft=LitCOffEE ts=4 +# vim:noexpandtab:ft=litcoffee +# vim:ts=4:sts=4 ft=litcoffee:noexpandtab:\x20 +# vim:noexpandtab titlestring=hi\|there\\\\ ft=litcoffee ts=4\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +ex: se filetype=litcoffee: +_vi: se filetype=litcoffee: + vi: se filetype=litcoffee +# vim set ft=illitcoffee +# vim: soft=litcoffee +# vim: clean-syntax=litcoffee: +# vim set ft=litcoffee: +# vim: setft=litcoffee: +# vim: se ft=litcoffee backupdir=tmp +# vim: set ft=LITCOFFEE set cmdheight=1 +# vim:noexpandtab sts:4 ft:litcoffee ts:4 +# vim:noexpandtab titlestring=hi\\|there\\ ft=litcoffee ts=4 +# vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=litcoffee ts=4\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + }); +}); diff --git a/packages/language-coffee-script/spec/coffee-script-spec.js b/packages/language-coffee-script/spec/coffee-script-spec.js new file mode 100644 index 0000000000..41a7a9c8ed --- /dev/null +++ b/packages/language-coffee-script/spec/coffee-script-spec.js @@ -0,0 +1,1630 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +const fs = require('fs'); +const path = require('path'); + +describe("CoffeeScript grammar", function() { + let grammar = null; + + beforeEach(function() { + waitsForPromise(() => atom.packages.activatePackage("language-coffee-script")); + + return runs(() => grammar = atom.grammars.grammarForScopeName("source.coffee")); + }); + + it("parses the grammar", function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe("source.coffee"); + }); + + it("tokenizes classes", function() { + let {tokens} = grammar.tokenizeLine("class Foo"); + + expect(tokens[0]).toEqual({value: "class", scopes: ["source.coffee", "meta.class.coffee", "storage.type.class.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); + expect(tokens[2]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.name.type.class.coffee"]}); + + ({tokens} = grammar.tokenizeLine("class_ Foo")); + expect(tokens[0]).toEqual({value: "class_", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + + ({tokens} = grammar.tokenizeLine("_class Foo")); + expect(tokens[0]).toEqual({value: "_class", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + + ({tokens} = grammar.tokenizeLine("[class Foo]")); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); + expect(tokens[1]).toEqual({value: "class", scopes: ["source.coffee", "meta.class.coffee", "storage.type.class.coffee"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); + expect(tokens[3]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.name.type.class.coffee"]}); + expect(tokens[4]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); + + ({tokens} = grammar.tokenizeLine("bar(class Foo)")); + expect(tokens[0]).toEqual({value: "bar", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[1]).toEqual({value: "(", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "punctuation.definition.arguments.begin.bracket.round.coffee"]}); + expect(tokens[2]).toEqual({value: "class", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee", "storage.type.class.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee"]}); + expect(tokens[4]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee", "entity.name.type.class.coffee"]}); + return expect(tokens[5]).toEqual({value: ")", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "punctuation.definition.arguments.end.bracket.round.coffee"]}); +}); + + it("tokenizes named subclasses", function() { + const {tokens} = grammar.tokenizeLine("class Foo extends Bar"); + + expect(tokens[0]).toEqual({value: "class", scopes: ["source.coffee", "meta.class.coffee", "storage.type.class.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); + expect(tokens[2]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.name.type.class.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); + expect(tokens[4]).toEqual({value: "extends", scopes: ["source.coffee", "meta.class.coffee", "keyword.control.inheritance.coffee"]}); + expect(tokens[5]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); + return expect(tokens[6]).toEqual({value: "Bar", scopes: ["source.coffee", "meta.class.coffee", "entity.other.inherited-class.coffee"]}); +}); + + it("tokenizes anonymous subclasses", function() { + const {tokens} = grammar.tokenizeLine("class extends Foo"); + + expect(tokens[0]).toEqual({value: "class", scopes: ["source.coffee", "meta.class.coffee", "storage.type.class.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); + expect(tokens[2]).toEqual({value: "extends", scopes: ["source.coffee", "meta.class.coffee", "keyword.control.inheritance.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); + return expect(tokens[4]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.other.inherited-class.coffee"]}); +}); + + it("tokenizes instantiated anonymous classes", function() { + const {tokens} = grammar.tokenizeLine("new class"); + + expect(tokens[0]).toEqual({value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"]}); + return expect(tokens[2]).toEqual({value: "class", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "storage.type.class.coffee"]}); +}); + + it("tokenizes instantiated named classes", function() { + let {tokens} = grammar.tokenizeLine("new class Foo"); + + expect(tokens[0]).toEqual({value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"]}); + expect(tokens[2]).toEqual({value: "class", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "storage.type.class.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"]}); + expect(tokens[4]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"]}); + + ({tokens} = grammar.tokenizeLine("new Foo")); + + expect(tokens[0]).toEqual({value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"]}); + return expect(tokens[2]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"]}); +}); + + it("tokenizes class names that start with `class` correctly", function() { + const {tokens} = grammar.tokenizeLine("new classTest"); + + expect(tokens[0]).toEqual({value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"]}); + return expect(tokens[2]).toEqual({value: "classTest", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"]}); +}); + + it("tokenizes comments", function() { + let {tokens} = grammar.tokenizeLine("# I am a comment"); + + expect(tokens[0]).toEqual({value: "#", scopes: ["source.coffee", "comment.line.number-sign.coffee", "punctuation.definition.comment.coffee"]}); + expect(tokens[1]).toEqual({value: " I am a comment", scopes: ["source.coffee", "comment.line.number-sign.coffee"]}); + + ({tokens} = grammar.tokenizeLine("\#{Comment}")); + + expect(tokens[0]).toEqual({value: "#", scopes: ["source.coffee", "comment.line.number-sign.coffee", "punctuation.definition.comment.coffee"]}); + return expect(tokens[1]).toEqual({value: "{Comment}", scopes: ["source.coffee", "comment.line.number-sign.coffee"]}); +}); + + it("tokenizes block comments", function() { + const lines = grammar.tokenizeLines(`\ +### I am a block comment +Very blocky +Until here +###\ +` + ); + expect(lines[0][0]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); + expect(lines[0][1]).toEqual({value: ' I am a block comment', scopes: ['source.coffee', 'comment.block.coffee']}); + expect(lines[2][0]).toEqual({value: 'Until here', scopes: ['source.coffee', 'comment.block.coffee']}); + expect(lines[3][0]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); + + const {tokens} = grammar.tokenizeLine("identity = ###::### (value ###: T ###) ###: T ### ->"); + expect(tokens[0]).toEqual({value: 'identity', scopes: ['source.coffee', 'variable.assignment.coffee']}); + expect(tokens[4]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); + expect(tokens[5]).toEqual({value: '::', scopes: ['source.coffee', 'comment.block.coffee']}); + expect(tokens[6]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); + expect(tokens[9]).toEqual({value: 'value ', scopes: ['source.coffee']}); // TODO: These scopes are incorrect and should be fixed + expect(tokens[10]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); + expect(tokens[11]).toEqual({value: ': T ', scopes: ['source.coffee', 'comment.block.coffee']}); + expect(tokens[12]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); + expect(tokens[14]).toEqual({value: ' ', scopes: ['source.coffee']}); // TODO: These scopes are incorrect and should be fixed + expect(tokens[15]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); + expect(tokens[16]).toEqual({value: ': T ', scopes: ['source.coffee', 'comment.block.coffee']}); + expect(tokens[17]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); + return expect(tokens[19]).toEqual({value: '->', scopes: ['source.coffee', 'meta.function.inline.coffee', 'storage.type.function.coffee']}); +}); + + it("tokenizes annotations in block comments", function() { + const lines = grammar.tokenizeLines(`\ +### + @foo - food +@bar - bart\ +` + ); + + expect(lines[1][0]).toEqual({value: ' ', scopes: ["source.coffee", "comment.block.coffee"]}); + expect(lines[1][1]).toEqual({value: '@foo', scopes: ["source.coffee", "comment.block.coffee", "storage.type.annotation.coffee"]}); + return expect(lines[2][0]).toEqual({value: '@bar', scopes: ["source.coffee", "comment.block.coffee", "storage.type.annotation.coffee"]}); +}); + + describe("numbers", function() { + it("tokenizes hexadecimals", function() { + let {tokens} = grammar.tokenizeLine('0x1D306'); + expect(tokens[0]).toEqual({value: '0x1D306', scopes: ['source.coffee', 'constant.numeric.hex.coffee']}); + + ({tokens} = grammar.tokenizeLine('0X1D306')); + return expect(tokens[0]).toEqual({value: '0X1D306', scopes: ['source.coffee', 'constant.numeric.hex.coffee']}); + }); + + it("tokenizes binary literals", function() { + let {tokens} = grammar.tokenizeLine('0b011101110111010001100110'); + expect(tokens[0]).toEqual({value: '0b011101110111010001100110', scopes: ['source.coffee', 'constant.numeric.binary.coffee']}); + + ({tokens} = grammar.tokenizeLine('0B011101110111010001100110')); + return expect(tokens[0]).toEqual({value: '0B011101110111010001100110', scopes: ['source.coffee', 'constant.numeric.binary.coffee']}); + }); + + it("tokenizes octal literals", function() { + let {tokens} = grammar.tokenizeLine('0o1411'); + expect(tokens[0]).toEqual({value: '0o1411', scopes: ['source.coffee', 'constant.numeric.octal.coffee']}); + + ({tokens} = grammar.tokenizeLine('0O1411')); + expect(tokens[0]).toEqual({value: '0O1411', scopes: ['source.coffee', 'constant.numeric.octal.coffee']}); + + ({tokens} = grammar.tokenizeLine('0010')); + return expect(tokens[0]).toEqual({value: '0010', scopes: ['source.coffee', 'constant.numeric.octal.coffee']}); + }); + + it("tokenizes decimals", function() { + let {tokens} = grammar.tokenizeLine('1234'); + expect(tokens[0]).toEqual({value: '1234', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + + ({tokens} = grammar.tokenizeLine('5e-10')); + expect(tokens[0]).toEqual({value: '5e-10', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + + ({tokens} = grammar.tokenizeLine('5E+5')); + expect(tokens[0]).toEqual({value: '5E+5', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + + ({tokens} = grammar.tokenizeLine('9.')); + expect(tokens[0]).toEqual({value: '9', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee']}); + + ({tokens} = grammar.tokenizeLine('.9')); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee']}); + expect(tokens[1]).toEqual({value: '9', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + + ({tokens} = grammar.tokenizeLine('9.9')); + expect(tokens[0]).toEqual({value: '9', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee']}); + expect(tokens[2]).toEqual({value: '9', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + + ({tokens} = grammar.tokenizeLine('.1e-23')); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee']}); + expect(tokens[1]).toEqual({value: '1e-23', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + + ({tokens} = grammar.tokenizeLine('1.E3')); + expect(tokens[0]).toEqual({value: '1', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee']}); + return expect(tokens[2]).toEqual({value: 'E3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + }); + + return it("does not tokenize numbers that are part of a variable", function() { + let {tokens} = grammar.tokenizeLine('hi$1'); + expect(tokens[0]).toEqual({value: 'hi$1', scopes: ['source.coffee']}); + + ({tokens} = grammar.tokenizeLine('hi_1')); + return expect(tokens[0]).toEqual({value: 'hi_1', scopes: ['source.coffee']}); + }); +}); + + it("tokenizes variable assignments", function() { + let {tokens} = grammar.tokenizeLine("something = b"); + expect(tokens[0]).toEqual({value: "something", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("something : b")); + expect(tokens[0]).toEqual({value: "something", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: ":", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a and= b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "and=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + // Should NOT be tokenized as and= + ({tokens} = grammar.tokenizeLine("operand=true")); + expect(tokens[0]).toEqual({value: "operand", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[1]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a or= b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "or=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + // Should NOT be tokenized as or= + ({tokens} = grammar.tokenizeLine("editor=false")); + expect(tokens[0]).toEqual({value: "editor", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[1]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a -= b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "-=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a += b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "+=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a /= b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "/=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a &= b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "&=", scopes: ["source.coffee", "keyword.operator.assignment.compound.bitwise.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a %= b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "%=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a *= b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "*=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a ?= b")); + expect(tokens[0]).toEqual({value: "a", scopes: ["source.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "?=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a == b")); + expect(tokens[0]).toEqual({value: "a ", scopes: ["source.coffee"]}); + expect(tokens[1]).toEqual({value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); + expect(tokens[2]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("false == b")); + expect(tokens[0]).toEqual({value: "false", scopes: ["source.coffee", "constant.language.boolean.false.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("true == b")); + expect(tokens[0]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("null == b")); + expect(tokens[0]).toEqual({value: "null", scopes: ["source.coffee", "constant.language.null.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("this == b")); + expect(tokens[0]).toEqual({value: "this", scopes: ["source.coffee", "variable.language.this.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); + return expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); +}); + + it("tokenizes compound operators properly", function() { + let tokens; + const assignmentOperators = ["and=", "or=", "&&=", "||=", "/=", "*=", "%=", "+=", "-="]; + const bitwiseOperators = ["<<=", ">>=", ">>>=", "&=", "|=", "^="]; + const comparisonOperators = ["==", "!=", "<=", ">="]; + + for (let assignmentOperator of Array.from(assignmentOperators)) { + ({tokens} = grammar.tokenizeLine(assignmentOperator)); + expect(tokens[0]).toEqual({value: assignmentOperator, scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"]}); + } + + for (let bitwiseOperator of Array.from(bitwiseOperators)) { + ({tokens} = grammar.tokenizeLine(bitwiseOperator)); + expect(tokens[0]).toEqual({value: bitwiseOperator, scopes: ["source.coffee", "keyword.operator.assignment.compound.bitwise.coffee"]}); + } + + return (() => { + const result = []; + for (let comparisonOperator of Array.from(comparisonOperators)) { + ({tokens} = grammar.tokenizeLine(comparisonOperator)); + result.push(expect(tokens[0]).toEqual({value: comparisonOperator, scopes: ["source.coffee", "keyword.operator.comparison.coffee"]})); + } + return result; + })(); +}); + + it("tokenizes operators properly", function() { + let tokens; + const logicalOperators = ["!", "&&", "||", "and", "or", "not"]; + const bitwiseOperators = ["^", "~", "&", "|"]; + const comparisonOperators = ["<", ">", "is", "isnt"]; + const decrementOperators = ["--"]; + const incrementOperators = ["++"]; + const splatOperators = ["..."]; + const existentialOperators = ["?"]; + const operators = ["%", "*", "/", "-", "+"]; + const keywords = ["delete", "instanceof", "new", "typeof"]; + + for (let logicalOperator of Array.from(logicalOperators)) { + ({tokens} = grammar.tokenizeLine(logicalOperator)); + expect(tokens[0]).toEqual({value: logicalOperator, scopes: ["source.coffee", "keyword.operator.logical.coffee"]}); + } + + for (let bitwiseOperator of Array.from(bitwiseOperators)) { + ({tokens} = grammar.tokenizeLine(bitwiseOperator)); + expect(tokens[0]).toEqual({value: bitwiseOperator, scopes: ["source.coffee", "keyword.operator.bitwise.coffee"]}); + } + + for (let comparisonOperator of Array.from(comparisonOperators)) { + ({tokens} = grammar.tokenizeLine(comparisonOperator)); + expect(tokens[0]).toEqual({value: comparisonOperator, scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); + } + + for (let decrementOperator of Array.from(decrementOperators)) { + ({tokens} = grammar.tokenizeLine(decrementOperator)); + expect(tokens[0]).toEqual({value: decrementOperator, scopes: ["source.coffee", "keyword.operator.decrement.coffee"]}); + } + + for (let incrementOperator of Array.from(incrementOperators)) { + ({tokens} = grammar.tokenizeLine(incrementOperator)); + expect(tokens[0]).toEqual({value: incrementOperator, scopes: ["source.coffee", "keyword.operator.increment.coffee"]}); + } + + for (let splatOperator of Array.from(splatOperators)) { + ({tokens} = grammar.tokenizeLine(splatOperator)); + expect(tokens[0]).toEqual({value: splatOperator, scopes: ["source.coffee", "keyword.operator.splat.coffee"]}); + } + + for (let existentialOperator of Array.from(existentialOperators)) { + ({tokens} = grammar.tokenizeLine(existentialOperator)); + expect(tokens[0]).toEqual({value: existentialOperator, scopes: ["source.coffee", "keyword.operator.existential.coffee"]}); + } + + for (let operator of Array.from(operators)) { + ({tokens} = grammar.tokenizeLine(operator)); + expect(tokens[0]).toEqual({value: operator, scopes: ["source.coffee", "keyword.operator.coffee"]}); + } + + return (() => { + const result = []; + for (let keyword of Array.from(keywords)) { + ({tokens} = grammar.tokenizeLine(keyword)); + result.push(expect(tokens[0]).toEqual({value: keyword, scopes: ["source.coffee", `keyword.operator.${keyword}.coffee`]})); + } + return result; + })(); +}); + + it("does not tokenize non-operators as operators", function() { + const notOperators = ["(/=", "-->", "=>", "->"]; + + return (() => { + const result = []; + for (let notOperator of Array.from(notOperators)) { + const {tokens} = grammar.tokenizeLine(notOperator); + result.push(expect(tokens[0]).not.toEqual({value: notOperator, scopes: ["source.coffee", "keyword.operator.coffee"]})); + } + return result; + })(); +}); + + describe("properties", function() { + it("tokenizes properties", function() { + let {tokens} = grammar.tokenizeLine('obj.property'); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[2]).toEqual({value: 'property', scopes: ['source.coffee', 'variable.other.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('obj.property instanceof Object')); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[2]).toEqual({value: 'property', scopes: ['source.coffee', 'variable.other.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('obj.property.property')); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[2]).toEqual({value: 'property', scopes: ['source.coffee', 'variable.other.object.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('obj.Property')); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[2]).toEqual({value: 'Property', scopes: ['source.coffee', 'variable.other.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('obj.prop1?.prop2?')); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[2]).toEqual({value: 'prop1', scopes: ['source.coffee', 'variable.other.object.property.coffee']}); + expect(tokens[3]).toEqual({value: '?', scopes: ['source.coffee', 'keyword.operator.existential.coffee']}); + expect(tokens[4]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[5]).toEqual({value: 'prop2', scopes: ['source.coffee', 'variable.other.property.coffee']}); + expect(tokens[6]).toEqual({value: '?', scopes: ['source.coffee', 'keyword.operator.existential.coffee']}); + + ({tokens} = grammar.tokenizeLine('obj.$abc$')); + expect(tokens[2]).toEqual({value: '$abc$', scopes: ['source.coffee', 'variable.other.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('obj.$$')); + expect(tokens[2]).toEqual({value: '$$', scopes: ['source.coffee', 'variable.other.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('a().b')); + expect(tokens[2]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + expect(tokens[3]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[4]).toEqual({value: 'b', scopes: ['source.coffee', 'variable.other.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.123illegal')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + return expect(tokens[2]).toEqual({value: '123illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + }); + + it("tokenizes constant properties", function() { + let {tokens} = grammar.tokenizeLine('obj.MY_CONSTANT'); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[2]).toEqual({value: 'MY_CONSTANT', scopes: ['source.coffee', 'constant.other.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('obj.MY_CONSTANT.prop')); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[2]).toEqual({value: 'MY_CONSTANT', scopes: ['source.coffee', 'constant.other.object.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.C')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); + return expect(tokens[2]).toEqual({value: 'C', scopes: ['source.coffee', 'constant.other.property.coffee']}); + }); + + return it("tokenizes objects, methods, and properties using :: prototype syntax", function() { + let {tokens} = grammar.tokenizeLine("Foo::"); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::true")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[2]).toEqual({value: "true", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::on")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[2]).toEqual({value: "on", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::yes")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[2]).toEqual({value: "yes", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::false")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[2]).toEqual({value: "false", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::off")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[2]).toEqual({value: "off", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::no")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[2]).toEqual({value: "no", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::null")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[2]).toEqual({value: "null", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::extends")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[2]).toEqual({value: "extends", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo :: something :: else")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[4]).toEqual({value: "something", scopes: ["source.coffee", "variable.other.object.property.coffee"]}); + expect(tokens[5]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[6]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); + expect(tokens[7]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[8]).toEqual({value: "else", scopes: ["source.coffee", "variable.other.property.coffee"]}); + + ({tokens} = grammar.tokenizeLine("Foo::toString()")); + expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); + expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "meta.method-call.coffee", "keyword.operator.prototype.coffee"]}); + return expect(tokens[2]).toEqual({value: "toString", scopes: ["source.coffee", "meta.method-call.coffee", "support.function.coffee"]}); + }); +}); + + describe("variables", function() { + it("tokenizes 'this'", function() { + let {tokens} = grammar.tokenizeLine('this'); + expect(tokens[0]).toEqual({value: 'this', scopes: ['source.coffee', 'variable.language.this.coffee']}); + + ({tokens} = grammar.tokenizeLine('this.obj.prototype = new El()')); + expect(tokens[0]).toEqual({value: 'this', scopes: ['source.coffee', 'variable.language.this.coffee']}); + + ({tokens} = grammar.tokenizeLine('$this')); + expect(tokens[0]).toEqual({value: '$this', scopes: ['source.coffee']}); + + ({tokens} = grammar.tokenizeLine('this$')); + return expect(tokens[0]).toEqual({value: 'this$', scopes: ['source.coffee']}); + }); + + it("tokenizes 'super'", function() { + const {tokens} = grammar.tokenizeLine('super'); + return expect(tokens[0]).toEqual({value: 'super', scopes: ['source.coffee', 'variable.language.super.coffee']}); + }); + + it("tokenizes 'arguments'", function() { + let {tokens} = grammar.tokenizeLine('arguments'); + expect(tokens[0]).toEqual({value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee']}); + + ({tokens} = grammar.tokenizeLine('arguments[0]')); + expect(tokens[0]).toEqual({value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee']}); + + ({tokens} = grammar.tokenizeLine('arguments.length')); + return expect(tokens[0]).toEqual({value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee']}); + }); + + return it("tokenizes illegal identifiers", function() { + let {tokens} = grammar.tokenizeLine('0illegal'); + expect(tokens[0]).toEqual({value: '0illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + + ({tokens} = grammar.tokenizeLine('123illegal')); + expect(tokens[0]).toEqual({value: '123illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + + ({tokens} = grammar.tokenizeLine('123$illegal')); + return expect(tokens[0]).toEqual({value: '123$illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + }); +}); + + describe("objects", function() { + it("tokenizes them", function() { + let {tokens} = grammar.tokenizeLine('obj.prop'); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + + ({tokens} = grammar.tokenizeLine('$abc$.prop')); + expect(tokens[0]).toEqual({value: '$abc$', scopes: ['source.coffee', 'variable.other.object.coffee']}); + + ({tokens} = grammar.tokenizeLine('$$.prop')); + expect(tokens[0]).toEqual({value: '$$', scopes: ['source.coffee', 'variable.other.object.coffee']}); + + ({tokens} = grammar.tokenizeLine('obj?.prop')); + expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); + return expect(tokens[1]).toEqual({value: '?', scopes: ['source.coffee', 'keyword.operator.existential.coffee']}); + }); + + return it("tokenizes illegal objects", function() { + let {tokens} = grammar.tokenizeLine('1.prop'); + expect(tokens[0]).toEqual({value: '1', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + + ({tokens} = grammar.tokenizeLine('123.prop')); + expect(tokens[0]).toEqual({value: '123', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + + ({tokens} = grammar.tokenizeLine('123a.prop')); + return expect(tokens[0]).toEqual({value: '123a', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + }); +}); + + describe("arrays", function() { + it("tokenizes basic arrays", function() { + const {tokens} = grammar.tokenizeLine('[a, "b", 3]'); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.coffee', 'punctuation.definition.array.begin.bracket.square.coffee']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.coffee']}); + expect(tokens[2]).toEqual({value: ',', scopes: ['source.coffee', 'punctuation.separator.delimiter.coffee']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.coffee']}); + expect(tokens[9]).toEqual({value: '3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + return expect(tokens[10]).toEqual({value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee']}); + }); + + return it("tokenizes inclusive and exclusive slices", function() { + let {tokens} = grammar.tokenizeLine('[a..3]'); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.coffee', 'punctuation.definition.array.begin.bracket.square.coffee']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.coffee']}); + expect(tokens[2]).toEqual({value: '..', scopes: ['source.coffee', 'keyword.operator.slice.inclusive.coffee']}); + expect(tokens[3]).toEqual({value: '3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[4]).toEqual({value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee']}); + + ({tokens} = grammar.tokenizeLine('[3...b]')); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.coffee', 'punctuation.definition.array.begin.bracket.square.coffee']}); + expect(tokens[1]).toEqual({value: '3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[2]).toEqual({value: '...', scopes: ['source.coffee', 'keyword.operator.slice.exclusive.coffee']}); + expect(tokens[3]).toEqual({value: 'b', scopes: ['source.coffee']}); + return expect(tokens[4]).toEqual({value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee']}); + }); +}); + + it("verifies that regular expressions have explicit count modifiers", function() { + let source = fs.readFileSync(path.resolve(__dirname, '..', 'grammars', 'coffeescript.cson'), 'utf8'); + expect(source.search(/{,/)).toEqual(-1); + + source = fs.readFileSync(path.resolve(__dirname, '..', 'grammars', 'coffeescript (literate).cson'), 'utf8'); + return expect(source.search(/{,/)).toEqual(-1); + }); + + it("tokenizes embedded JavaScript", function() { + waitsForPromise(() => atom.packages.activatePackage("language-javascript")); + + return runs(function() { + let {tokens} = grammar.tokenizeLine("`;`"); + expect(tokens[0]).toEqual({value: "`", scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[1]).toEqual({value: ";", scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "punctuation.terminator.statement.js"]}); + expect(tokens[2]).toEqual({value: "`", scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.end.coffee"]}); + + const lines = grammar.tokenizeLines(`\ +\`var a = 1;\` +a = 2\ +` + ); + expect(lines[0][0]).toEqual({value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(lines[0][1]).toEqual({value: 'var', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "storage.type.var.js"]}); + expect(lines[0][6]).toEqual({value: ';', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "punctuation.terminator.statement.js"]}); + expect(lines[0][7]).toEqual({value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.end.coffee"]}); + expect(lines[1][0]).toEqual({value: 'a', scopes: ["source.coffee", "variable.assignment.coffee"]}); + + ({tokens} = grammar.tokenizeLine("`// comment` a = 2")); + expect(tokens[0]).toEqual({value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[1]).toEqual({value: '//', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "comment.line.double-slash.js", "punctuation.definition.comment.js"]}); + expect(tokens[2]).toEqual({value: ' comment', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "comment.line.double-slash.js"]}); + expect(tokens[3]).toEqual({value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.end.coffee"]}); + return expect(tokens[5]).toEqual({value: 'a', scopes: ["source.coffee", "variable.assignment.coffee"]});}); +}); + + describe("function calls", function() { + it("tokenizes function calls", function() { + let {tokens} = grammar.tokenizeLine('functionCall()'); + expect(tokens[0]).toEqual({value: 'functionCall', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + expect(tokens[2]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + + ({tokens} = grammar.tokenizeLine('functionCall(arg1, "test", {a: 123})')); + expect(tokens[0]).toEqual({value: 'functionCall', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + expect(tokens[2]).toEqual({value: 'arg1', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee']}); + expect(tokens[3]).toEqual({value: ',', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.delimiter.coffee']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[6]).toEqual({value: 'test', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee']}); + expect(tokens[8]).toEqual({value: ',', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.delimiter.coffee']}); + expect(tokens[10]).toEqual({value: '{', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.curly.coffee']}); + expect(tokens[11]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'variable.assignment.coffee']}); + expect(tokens[12]).toEqual({value: ':', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'keyword.operator.assignment.coffee']}); + expect(tokens[14]).toEqual({value: '123', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[15]).toEqual({value: '}', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.curly.coffee']}); + expect(tokens[16]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + + ({tokens} = grammar.tokenizeLine('functionCall((123).toString())')); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + expect(tokens[2]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.round.coffee']}); + expect(tokens[3]).toEqual({value: '123', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[4]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.round.coffee']}); + expect(tokens[9]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + + ({tokens} = grammar.tokenizeLine('$abc$()')); + expect(tokens[0]).toEqual({value: '$abc$', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('$$()')); + expect(tokens[0]).toEqual({value: '$$', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('ABC()')); + expect(tokens[0]).toEqual({value: 'ABC', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('$ABC$()')); + expect(tokens[0]).toEqual({value: '$ABC$', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('@$()')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.coffee', 'meta.function-call.coffee', 'variable.other.readwrite.instance.coffee']}); + expect(tokens[1]).toEqual({value: '$', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('functionCall arg1, "test", {a: 123}')); + expect(tokens[0]).toEqual({value: 'functionCall', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[2]).toEqual({value: 'arg1', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee']}); + expect(tokens[3]).toEqual({value: ',', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.delimiter.coffee']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[6]).toEqual({value: 'test', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee']}); + expect(tokens[8]).toEqual({value: ',', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.delimiter.coffee']}); + expect(tokens[10]).toEqual({value: '{', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.curly.coffee']}); + expect(tokens[11]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'variable.assignment.coffee']}); + expect(tokens[12]).toEqual({value: ':', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'keyword.operator.assignment.coffee']}); + expect(tokens[14]).toEqual({value: '123', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[15]).toEqual({value: '}', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.curly.coffee']}); + + ({tokens} = grammar.tokenizeLine("foo bar")); + expect(tokens[0]).toEqual({value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.function-call.coffee"]}); + expect(tokens[2]).toEqual({value: "bar", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"]}); + + ({tokens} = grammar.tokenizeLine("foo not food")); + expect(tokens[0]).toEqual({value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.function-call.coffee"]}); + expect(tokens[2]).toEqual({value: "not", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "keyword.operator.logical.coffee"]}); + expect(tokens[3]).toEqual({value: " food", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"]}); + + ({tokens} = grammar.tokenizeLine("eat food for food in foods")); + expect(tokens[0]).toEqual({value: "eat", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[2]).toEqual({value: "food", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"]}); + expect(tokens[4]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[5]).toEqual({value: " food ", scopes: ["source.coffee"]}); + expect(tokens[6]).toEqual({value: "in", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[7]).toEqual({value: " foods", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("(eat food for food in get foods)")); + expect(tokens[0]).toEqual({value: "(", scopes: ["source.coffee", "meta.brace.round.coffee"]}); + expect(tokens[1]).toEqual({value: "eat", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[3]).toEqual({value: "food", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"]}); + expect(tokens[5]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[6]).toEqual({value: " food ", scopes: ["source.coffee"]}); + expect(tokens[7]).toEqual({value: "in", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[9]).toEqual({value: "get", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[11]).toEqual({value: "foods", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"]}); + expect(tokens[12]).toEqual({value: ")", scopes: ["source.coffee", "meta.brace.round.coffee"]}); + + ({tokens} = grammar.tokenizeLine("[eat food]")); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); + expect(tokens[1]).toEqual({value: "eat", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[3]).toEqual({value: "food", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"]}); + expect(tokens[4]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); + + ({tokens} = grammar.tokenizeLine("foo @bar")); + expect(tokens[0]).toEqual({value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[2]).toEqual({value: "@bar", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "variable.other.readwrite.instance.coffee"]}); + + ({tokens} = grammar.tokenizeLine("@foo bar")); + expect(tokens[0]).toEqual({value: "@", scopes: ["source.coffee", "meta.function-call.coffee", "variable.other.readwrite.instance.coffee"]}); + expect(tokens[1]).toEqual({value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[3]).toEqual({value: "bar", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"]}); + + ({tokens} = grammar.tokenizeLine("foo baz, @bar")); + expect(tokens[0]).toEqual({value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + expect(tokens[2]).toEqual({value: "baz", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"]}); + expect(tokens[3]).toEqual({value: ",", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[5]).toEqual({value: "@bar", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "variable.other.readwrite.instance.coffee"]}); + + ({tokens} = grammar.tokenizeLine("$ @$")); + expect(tokens[0]).toEqual({value: "$", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); + return expect(tokens[2]).toEqual({value: "@$", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "variable.other.readwrite.instance.coffee"]}); + }); + + it("tokenizes function calls when they are arguments", function() { + let {tokens} = grammar.tokenizeLine('a(b(c))'); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + expect(tokens[4]).toEqual({value: 'c', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee']}); + expect(tokens[5]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + expect(tokens[6]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + + ({tokens} = grammar.tokenizeLine('a b c')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + return expect(tokens[4]).toEqual({value: 'c', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee']}); + }); + + it("tokenizes illegal function calls", function() { + const {tokens} = grammar.tokenizeLine('0illegal()'); + expect(tokens[0]).toEqual({value: '0illegal', scopes: ['source.coffee', 'meta.function-call.coffee', 'invalid.illegal.identifier.coffee']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + return expect(tokens[2]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + }); + + it("tokenizes illegal arguments", function() { + let {tokens} = grammar.tokenizeLine('a(1a)'); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + expect(tokens[2]).toEqual({value: '1a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee']}); + expect(tokens[3]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + + ({tokens} = grammar.tokenizeLine('a(123a)')); + expect(tokens[2]).toEqual({value: '123a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee']}); + + ({tokens} = grammar.tokenizeLine('a(1.prop)')); + expect(tokens[2]).toEqual({value: '1', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee']}); + expect(tokens[3]).toEqual({value: '.', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.property.period.coffee']}); + expect(tokens[4]).toEqual({value: 'prop', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'variable.other.property.coffee']}); + + ({tokens} = grammar.tokenizeLine('a 1a')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + return expect(tokens[2]).toEqual({value: '1a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee']}); + }); + + it("tokenizes function declaration as an argument", function() { + const {tokens} = grammar.tokenizeLine('a((p) -> return p )'); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + expect(tokens[2]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.begin.bracket.round.coffee']}); + expect(tokens[3]).toEqual({value: 'p', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'variable.parameter.function.coffee']}); + expect(tokens[4]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.end.bracket.round.coffee']}); + expect(tokens[8]).toEqual({value: 'return', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'keyword.control.coffee']}); + expect(tokens[9]).toEqual({value: ' p ', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee']}); + return expect(tokens[10]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + }); + + it("does not tokenize booleans as function calls", function() { + let {tokens} = grammar.tokenizeLine("false unless true"); + expect(tokens[0]).toEqual({value: "false", scopes: ["source.coffee", "constant.language.boolean.false.coffee"]}); + expect(tokens[2]).toEqual({value: "unless", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[4]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); + + ({tokens} = grammar.tokenizeLine("true if false")); + expect(tokens[0]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); + expect(tokens[2]).toEqual({value: "if", scopes: ["source.coffee", "keyword.control.coffee"]}); + return expect(tokens[4]).toEqual({value: "false", scopes: ["source.coffee", "constant.language.boolean.false.coffee"]}); + }); + + return it("does not tokenize comparison operators as function calls", function() { + const {tokens} = grammar.tokenizeLine("if a is b"); + expect(tokens[1]).toEqual({value: " a ", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: "is", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); + return expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + }); +}); + + describe("functions", function() { + it("tokenizes regular functions", function() { + let {tokens} = grammar.tokenizeLine("foo = -> 1"); + expect(tokens[0]).toEqual({value: "foo", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[2]).toEqual({value: "=", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[4]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"]}); + expect(tokens[5]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[6]).toEqual({value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); + + ({tokens} = grammar.tokenizeLine("@foo = -> 1")); + expect(tokens[0]).toEqual({value: "@", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee", "variable.other.readwrite.instance.coffee"]}); + expect(tokens[1]).toEqual({value: "foo", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"]}); + expect(tokens[3]).toEqual({value: "=", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"]}); + + ({tokens} = grammar.tokenizeLine("$ = => 1")); + expect(tokens[0]).toEqual({value: "$", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"]}); + expect(tokens[2]).toEqual({value: "=", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"]}); + + ({tokens} = grammar.tokenizeLine("foo: -> 1")); + expect(tokens[0]).toEqual({value: "foo", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"]}); + expect(tokens[1]).toEqual({value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[3]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[5]).toEqual({value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); + + ({tokens} = grammar.tokenizeLine("'quoted': (a) => true")); + expect(tokens[0]).toEqual({value: "'", scopes: ["source.coffee", "meta.function.coffee", "string.quoted.single.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[1]).toEqual({value: "quoted", scopes: ["source.coffee", "meta.function.coffee", "string.quoted.single.coffee", "entity.name.function.coffee"]}); + expect(tokens[2]).toEqual({value: "'", scopes: ["source.coffee", "meta.function.coffee", "string.quoted.single.coffee", "punctuation.definition.string.end.coffee"]}); + expect(tokens[3]).toEqual({value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[5]).toEqual({value: "(", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"]}); + expect(tokens[6]).toEqual({value: "a", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[7]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[9]).toEqual({value: "=>", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"]}); + expect(tokens[10]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[11]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); + + ({tokens} = grammar.tokenizeLine('"quoted": (a) -> true')); + expect(tokens[0]).toEqual({value: '"', scopes: ["source.coffee", "meta.function.coffee", "string.quoted.double.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[1]).toEqual({value: "quoted", scopes: ["source.coffee", "meta.function.coffee", "string.quoted.double.coffee", "entity.name.function.coffee"]}); + expect(tokens[2]).toEqual({value: '"', scopes: ["source.coffee", "meta.function.coffee", "string.quoted.double.coffee", "punctuation.definition.string.end.coffee"]}); + expect(tokens[3]).toEqual({value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[5]).toEqual({value: "(", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"]}); + expect(tokens[6]).toEqual({value: "a", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[7]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[9]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"]}); + expect(tokens[10]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[11]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); + + ({tokens} = grammar.tokenizeLine("hello: (a) -> 1")); + expect(tokens[0]).toEqual({value: "hello", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"]}); + expect(tokens[1]).toEqual({value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[3]).toEqual({value: "(", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"]}); + expect(tokens[4]).toEqual({value: "a", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[5]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); + expect(tokens[6]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee"]}); + expect(tokens[7]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"]}); + expect(tokens[9]).toEqual({value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); + + ({tokens} = grammar.tokenizeLine("hello: (a, b, {c, d}, e = 'test', f = 3, g = -> 4) -> 1")); + expect(tokens[0]).toEqual({value: "hello", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"]}); + expect(tokens[1]).toEqual({value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[3]).toEqual({value: "(", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"]}); + expect(tokens[4]).toEqual({value: "a", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[5]).toEqual({value: ",", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[6]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee"]}); + expect(tokens[7]).toEqual({value: "b", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[8]).toEqual({value: ",", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[10]).toEqual({value: "{", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "meta.brace.curly.coffee"]}); + expect(tokens[11]).toEqual({value: "c", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee"]}); + expect(tokens[12]).toEqual({value: ",", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[13]).toEqual({value: " d", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee"]}); + expect(tokens[14]).toEqual({value: "}", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "meta.brace.curly.coffee"]}); + expect(tokens[17]).toEqual({value: "e", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[19]).toEqual({value: "=", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[21]).toEqual({value: "'", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "string.quoted.single.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[24]).toEqual({value: ",", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[26]).toEqual({value: "f", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[30]).toEqual({value: "3", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "constant.numeric.decimal.coffee"]}); + expect(tokens[33]).toEqual({value: "g", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[35]).toEqual({value: "=", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[37]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); + expect(tokens[40]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); + return expect(tokens[42]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"]}); + }); + + return it("tokenizes inline functions", function() { + let {tokens} = grammar.tokenizeLine("-> true"); + expect(tokens[0]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine(" -> true")); + expect(tokens[0]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[1]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("->true")); + expect(tokens[0]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); + + ({tokens} = grammar.tokenizeLine("(arg) -> true")); + expect(tokens[0]).toEqual({value: "(", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"]}); + expect(tokens[1]).toEqual({value: "arg", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[2]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.inline.coffee"]}); + expect(tokens[4]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); + expect(tokens[5]).toEqual({value: " ", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("(arg1, arg2) -> true")); + expect(tokens[0]).toEqual({value: "(", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"]}); + expect(tokens[1]).toEqual({value: "arg1", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[2]).toEqual({value: ",", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"]}); + expect(tokens[4]).toEqual({value: "arg2", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[5]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); + expect(tokens[6]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.inline.coffee"]}); + expect(tokens[7]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("( arg1, arg2 )-> true")); + expect(tokens[0]).toEqual({value: "(", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"]}); + expect(tokens[2]).toEqual({value: "arg1", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[3]).toEqual({value: ",", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"]}); + expect(tokens[5]).toEqual({value: "arg2", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"]}); + expect(tokens[6]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"]}); + expect(tokens[7]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); + expect(tokens[8]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); + return expect(tokens[9]).toEqual({value: " ", scopes: ["source.coffee"]}); + }); +}); + + describe("method calls", () => it("tokenizes method calls", function() { + let {tokens} = grammar.tokenizeLine('a.b(1+1)'); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + expect(tokens[4]).toEqual({value: '1', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[5]).toEqual({value: '+', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'keyword.operator.coffee']}); + expect(tokens[6]).toEqual({value: '1', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[7]).toEqual({value: ')', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + + ({tokens} = grammar.tokenizeLine('a . b(1+1)')); + expect(tokens[2]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); + expect(tokens[4]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[5]).toEqual({value: '(', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.$abc$()')); + expect(tokens[2]).toEqual({value: '$abc$', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.$$()')); + expect(tokens[2]).toEqual({value: '$$', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.b c')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee']}); + expect(tokens[4]).toEqual({value: 'c', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee']}); + + ({tokens} = grammar.tokenizeLine('(a.b c)')); + expect(tokens[0]).toEqual({value: '(', scopes: ['source.coffee', 'meta.brace.round.coffee']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[2]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); + expect(tokens[3]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[4]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee']}); + expect(tokens[5]).toEqual({value: 'c', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee']}); + expect(tokens[6]).toEqual({value: ')', scopes: ['source.coffee', 'meta.brace.round.coffee']}); + + ({tokens} = grammar.tokenizeLine("[a.b c]")); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[2]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); + expect(tokens[3]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[4]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee']}); + expect(tokens[5]).toEqual({value: 'c', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee']}); + expect(tokens[6]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); + + ({tokens} = grammar.tokenizeLine('a.b not c')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee']}); + expect(tokens[4]).toEqual({value: 'not', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'keyword.operator.logical.coffee']}); + expect(tokens[5]).toEqual({value: ' c', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.b 1+1')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee']}); + expect(tokens[4]).toEqual({value: '1', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[5]).toEqual({value: '+', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'keyword.operator.coffee']}); + expect(tokens[6]).toEqual({value: '1', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.b @')); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[4]).toEqual({value: '@', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'variable.other.readwrite.instance.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.$abc$ "q"')); + expect(tokens[2]).toEqual({value: '$abc$', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.$$ 4')); + expect(tokens[2]).toEqual({value: '$$', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + + ({tokens} = grammar.tokenizeLine('a.b @$')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee']}); + return expect(tokens[4]).toEqual({value: '@$', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'variable.other.readwrite.instance.coffee']}); +})); + + describe("destructuring assignments", function() { + it("tokenizes object and array destructuring", function() { + let {tokens} = grammar.tokenizeLine("{something} = hi"); + expect(tokens[0]).toEqual({value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"]}); + expect(tokens[1]).toEqual({value: "something", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[4]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[5]).toEqual({value: " hi", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("[x, y] = browserWindow.getPosition()")); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.begin.bracket.square.coffee"]}); + expect(tokens[1]).toEqual({value: "x", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "variable.assignment.coffee"]}); + expect(tokens[2]).toEqual({value: ",", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee"]}); + expect(tokens[4]).toEqual({value: "y", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "variable.assignment.coffee"]}); + expect(tokens[5]).toEqual({value: "]", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.end.bracket.square.coffee"]}); + expect(tokens[6]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[7]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.coffee"]}); + + ({tokens} = grammar.tokenizeLine("{'} ='}")); // Make sure this *isn't* tokenized as a destructuring assignment + expect(tokens[0]).not.toEqual({value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"]}); + return expect(tokens[0]).toEqual({value: "{", scopes: ["source.coffee", "meta.brace.curly.coffee"]}); + }); + + it("tokenizes nested destructuring assignments", function() { + const {tokens} = grammar.tokenizeLine("{poet: {name, address: [street, city]}} = futurists"); + expect(tokens[0]).toEqual({value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"]}); + expect(tokens[4]).toEqual({value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"]}); + expect(tokens[11]).toEqual({value: "[", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.begin.bracket.square.coffee"]}); + expect(tokens[16]).toEqual({value: "]", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.end.bracket.square.coffee"]}); + expect(tokens[17]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); + expect(tokens[18]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); + expect(tokens[19]).toEqual({value: " ", scopes: ["source.coffee"]}); + return expect(tokens[20]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + }); + + it("tokenizes multiple nested destructuring assignments", function() { + const {tokens} = grammar.tokenizeLine("{start: {row: startRow}, end: {row: endRow}} = range"); + expect(tokens[0]).toEqual({value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"]}); + expect(tokens[4]).toEqual({value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"]}); + expect(tokens[9]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); + expect(tokens[15]).toEqual({value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"]}); + expect(tokens[20]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); + expect(tokens[21]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); + expect(tokens[22]).toEqual({value: " ", scopes: ["source.coffee"]}); + return expect(tokens[23]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + }); + + return it("doesn't tokenize nested brackets as destructuring assignments", function() { + const {tokens} = grammar.tokenizeLine("[Point(0, 1), [Point(0, 0), Point(0, 1)]]"); + expect(tokens[0]).not.toEqual({value: "[", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.begin.bracket.square.coffee"]}); + return expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); + }); +}); + + it("tokenizes inline constant followed by unless statement correctly", function() { + const {tokens} = grammar.tokenizeLine("return 0 unless true"); + expect(tokens[0]).toEqual({value: "return", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[2]).toEqual({value: "0", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); + expect(tokens[4]).toEqual({value: "unless", scopes: ["source.coffee", "keyword.control.coffee"]}); + return expect(tokens[6]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); +}); + + describe("for loops", function() { + it("tokenizes for-in loops", function() { + const {tokens} = grammar.tokenizeLine("for food in foods"); + expect(tokens[0]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[1]).toEqual({value: " food ", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: "in", scopes: ["source.coffee", "keyword.control.coffee"]}); + return expect(tokens[3]).toEqual({value: " foods", scopes: ["source.coffee"]}); + }); + + it("tokenizes for-of loops", function() { + const {tokens} = grammar.tokenizeLine("for food, type of foods"); + expect(tokens[0]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[1]).toEqual({value: " food", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: ",", scopes: ["source.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[3]).toEqual({value: " type ", scopes: ["source.coffee"]}); + expect(tokens[4]).toEqual({value: "of", scopes: ["source.coffee", "keyword.control.coffee"]}); + return expect(tokens[5]).toEqual({value: " foods", scopes: ["source.coffee"]}); + }); + + it("tokenizes loops using arrays", function() { + const {tokens} = grammar.tokenizeLine("for food in ['broccoli', 'spinach', 'chocolate']"); + expect(tokens[0]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[1]).toEqual({value: " food ", scopes: ["source.coffee"]}); + expect(tokens[2]).toEqual({value: "in", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[4]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); + return expect(tokens[18]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); + }); + + it("tokenizes loops using the optional `when` keyword", function() { + const {tokens} = grammar.tokenizeLine("for food in foods when food isnt chocolate"); + expect(tokens[0]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[3]).toEqual({value: " foods ", scopes: ["source.coffee"]}); + expect(tokens[4]).toEqual({value: "when", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[5]).toEqual({value: " food ", scopes: ["source.coffee"]}); + expect(tokens[6]).toEqual({value: "isnt", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); + return expect(tokens[7]).toEqual({value: " chocolate", scopes: ["source.coffee"]}); + }); + + return it("tokenizes loops using the optional `by` keyword", function() { + const {tokens} = grammar.tokenizeLine("for food in foods by -1"); + expect(tokens[0]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[3]).toEqual({value: " foods ", scopes: ["source.coffee"]}); + expect(tokens[4]).toEqual({value: "by", scopes: ["source.coffee", "keyword.control.coffee"]}); + expect(tokens[5]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[6]).toEqual({value: "-", scopes: ["source.coffee", "keyword.operator.coffee"]}); + return expect(tokens[7]).toEqual({value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); + }); +}); + + describe("regular expressions", function() { + beforeEach(() => waitsForPromise(() => atom.packages.activatePackage("language-javascript"))); // Provides the regexp subgrammar + + it("tokenizes regular expressions", function() { + let {tokens} = grammar.tokenizeLine("/test/"); + expect(tokens[0]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[1]).toEqual({value: "test", scopes: ["source.coffee", "string.regexp.coffee"]}); + expect(tokens[2]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + + ({tokens} = grammar.tokenizeLine("/{'}/")); + expect(tokens[0]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[2]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + + ({tokens} = grammar.tokenizeLine("foo + /test/")); + expect(tokens[0]).toEqual({value: "foo ", scopes: ["source.coffee"]}); + expect(tokens[1]).toEqual({value: "+", scopes: ["source.coffee", "keyword.operator.coffee"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[3]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[4]).toEqual({value: "test", scopes: ["source.coffee", "string.regexp.coffee"]}); + return expect(tokens[5]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + }); + + it("tokenizes regular expressions containing spaces", function() { + const {tokens} = grammar.tokenizeLine("/ te st /"); + expect(tokens[0]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[1]).toEqual({value: " te st ", scopes: ["source.coffee", "string.regexp.coffee"]}); + return expect(tokens[2]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + }); + + it("tokenizes regular expressions containing escaped forward slashes", function() { + let {tokens} = grammar.tokenizeLine("/test\\//"); + expect(tokens[0]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[1]).toEqual({value: "test", scopes: ["source.coffee", "string.regexp.coffee"]}); + expect(tokens[2]).toEqual({value: "\\/", scopes: ["source.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"]}); + expect(tokens[3]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + + ({tokens} = grammar.tokenizeLine("/one\\/two!\\/three/")); + expect(tokens[0]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[1]).toEqual({value: "one", scopes: ["source.coffee", "string.regexp.coffee"]}); + expect(tokens[2]).toEqual({value: "\\/", scopes: ["source.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"]}); + expect(tokens[3]).toEqual({value: "two!", scopes: ["source.coffee", "string.regexp.coffee"]}); + expect(tokens[4]).toEqual({value: "\\/", scopes: ["source.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"]}); + expect(tokens[5]).toEqual({value: "three", scopes: ["source.coffee", "string.regexp.coffee"]}); + return expect(tokens[6]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + }); + + it("tokenizes regular expressions inside arrays", function() { + let {tokens} = grammar.tokenizeLine("[/test/]"); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); + expect(tokens[1]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[2]).toEqual({value: "test", scopes: ["source.coffee", "string.regexp.coffee"]}); + expect(tokens[3]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + expect(tokens[4]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); + + ({tokens} = grammar.tokenizeLine("[1, /test/]")); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); + expect(tokens[1]).toEqual({value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); + expect(tokens[2]).toEqual({value: ",", scopes: ["source.coffee", "punctuation.separator.delimiter.coffee"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[4]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[5]).toEqual({value: "test", scopes: ["source.coffee", "string.regexp.coffee"]}); + expect(tokens[6]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + return expect(tokens[7]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); + }); + + it("does not tokenize multiple division as regex", function() { + // https://github.com/atom/language-coffee-script/issues/112 + let {tokens} = grammar.tokenizeLine("a / b + c / d"); + expect(tokens[1]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); + expect(tokens[2]).toEqual({value: " b ", scopes: ["source.coffee"]}); + expect(tokens[5]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); + + ({tokens} = grammar.tokenizeLine("a / 2 / (3)")); + expect(tokens[1]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); + expect(tokens[3]).toEqual({value: "2", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); + return expect(tokens[5]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); + }); + + it("does not tokenize comments with URLs in them as regex", function() { + // Disclaimer: This does not fix when comments contain only slashes, such as `a / something # comment /` + const {tokens} = grammar.tokenizeLine("canvas.width/2 # https://github.com/atom/language-coffee-script/issues/112"); + expect(tokens[3]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); + expect(tokens[6]).toEqual({value: "#", scopes: ["source.coffee", "comment.line.number-sign.coffee", "punctuation.definition.comment.coffee"]}); + return expect(tokens[7]).toEqual({value: " https://github.com/atom/language-coffee-script/issues/112", scopes: ["source.coffee", "comment.line.number-sign.coffee"]}); + }); + + it("stops tokenizing regex at the first non-escaped forwards slash", function() { + let {tokens} = grammar.tokenizeLine("path.replace(/\\\\/g, '/')"); + expect(tokens[4]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[6]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + expect(tokens[11]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.quoted.single.coffee"]}); + + ({tokens} = grammar.tokenizeLine("path.replace(/\\\\\\//g, '/')")); + expect(tokens[4]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); + expect(tokens[6]).toEqual({value: "\\/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"]}); + expect(tokens[7]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + return expect(tokens[12]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.quoted.single.coffee"]}); + }); + + return it("tokenises multi-line regular expressions", function() { + const {tokens} = grammar.tokenizeLine('/// (XYZ) ///'); + expect(tokens[0]).toEqual({value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[2]).toEqual({value: '(', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'meta.group.regexp', 'punctuation.definition.group.regexp']}); + expect(tokens[3]).toEqual({value: 'XYZ', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'meta.group.regexp']}); + expect(tokens[4]).toEqual({value: ')', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'meta.group.regexp', 'punctuation.definition.group.regexp']}); + expect(tokens[6]).toEqual({value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.end.coffee']}); + + const lines = grammar.tokenizeLines(`\ +/// +XYZ // +/~/ +///\ +` + ); + expect(lines[0][0]).toEqual({value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(lines[1][0]).toEqual({value: 'XYZ //', scopes: ['source.coffee', 'string.regexp.multiline.coffee']}); + expect(lines[2][0]).toEqual({value: '/~/', scopes: ['source.coffee', 'string.regexp.multiline.coffee']}); + return expect(lines[3][0]).toEqual({value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.end.coffee']}); + }); +}); + + describe("here-docs", function() { + it("tokenises single-quoted here-docs", function() { + const {tokens} = grammar.tokenizeLine("'''XYZ'''"); + expect(tokens[0]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[1]).toEqual({value: 'XYZ', scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee']}); + expect(tokens[2]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.end.coffee']}); + + const lines = grammar.tokenizeLines(`\ +''' +'ABC' +XYZ '' +'''\ +` + ); + expect(lines[0][0]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(lines[1][0]).toEqual({value: "'ABC'", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee']}); + expect(lines[2][0]).toEqual({value: "XYZ ''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee']}); + return expect(lines[3][0]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.end.coffee']}); + }); + + return it("tokenises double-quoted here-docs", function() { + const {tokens} = grammar.tokenizeLine("'''XYZ'''"); + expect(tokens[0]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[1]).toEqual({value: 'XYZ', scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee']}); + expect(tokens[2]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.end.coffee']}); + + const lines = grammar.tokenizeLines(`\ +""" +"ABC" +XYZ "" +"""\ +` + ); + expect(lines[0][0]).toEqual({value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(lines[1][0]).toEqual({value: '"ABC"', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee']}); + expect(lines[2][0]).toEqual({value: 'XYZ ""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee']}); + return expect(lines[3][0]).toEqual({value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.end.coffee']}); + }); +}); + + describe("escape sequences in strings", function() { + it("tokenises leading backslashes in double-quoted strings", function() { + let {tokens} = grammar.tokenizeLine('"a\\\\b\\\\\\\\c"'); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.double.coffee']}); + expect(tokens[2]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[3]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[4]).toEqual({value: 'b', scopes: ['source.coffee', 'string.quoted.double.coffee']}); + expect(tokens[5]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[6]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[7]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[8]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[9]).toEqual({value: 'c', scopes: ['source.coffee', 'string.quoted.double.coffee']}); + expect(tokens[10]).toEqual({value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee']}); + + ({tokens} = grammar.tokenizeLine('"\\a\\t\\a\\b"')); + expect(tokens[0]).toEqual({value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[1]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[2]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[3]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[4]).toEqual({value: 't', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[5]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[6]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[7]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[8]).toEqual({value: 'b', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); + return expect(tokens[9]).toEqual({value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee']}); + }); + + return it("tokenises leading backslashes in single-quoted strings", function() { + let {tokens} = grammar.tokenizeLine("'a\\\\b\\\\\\\\c'"); + expect(tokens[0]).toEqual({value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.single.coffee']}); + expect(tokens[2]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[3]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[4]).toEqual({value: 'b', scopes: ['source.coffee', 'string.quoted.single.coffee']}); + expect(tokens[5]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[6]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[7]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[8]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[9]).toEqual({value: 'c', scopes: ['source.coffee', 'string.quoted.single.coffee']}); + expect(tokens[10]).toEqual({value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee']}); + + ({tokens} = grammar.tokenizeLine("'\\a\\t\\a\\b'")); + expect(tokens[0]).toEqual({value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.begin.coffee']}); + expect(tokens[1]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[2]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[3]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[4]).toEqual({value: 't', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[5]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[6]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); + expect(tokens[7]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); + expect(tokens[8]).toEqual({value: 'b', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); + return expect(tokens[9]).toEqual({value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee']}); + }); +}); + + describe("jsx", function() { + it("tokenises HTML tags", function() { + let {tokens} = grammar.tokenizeLine("
"); + expect(tokens[0]).toEqual({value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']}); + expect(tokens[1]).toEqual({value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]}); + expect(tokens[2]).toEqual({value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + expect(tokens[3]).toEqual({value: '', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + + ({tokens} = grammar.tokenizeLine("
")); + expect(tokens[0]).toEqual({value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']}); + expect(tokens[1]).toEqual({value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]}); + return expect(tokens[2]).toEqual({value: '/>', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + }); + + it("tokenises HTML tags with attributes", function() { + const {tokens} = grammar.tokenizeLine("
"); + expect(tokens[0]).toEqual({value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']}); + expect(tokens[1]).toEqual({value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + expect(tokens[3]).toEqual({value: 'class', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ]}); + expect(tokens[4]).toEqual({value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ]}); + expect(tokens[5]).toEqual({value: '\'', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.begin.coffee' ]}); + expect(tokens[6]).toEqual({value: 'myclass', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee' ]}); + expect(tokens[7]).toEqual({value: '\'', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee' ]}); + expect(tokens[8]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + expect(tokens[9]).toEqual({value: 'id', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ]}); + expect(tokens[10]).toEqual({value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ]}); + expect(tokens[11]).toEqual({value: '"', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee' ]}); + expect(tokens[12]).toEqual({value: 'myid', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee' ]}); + expect(tokens[13]).toEqual({value: '"', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee' ]}); + return expect(tokens[14]).toEqual({value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + }); + + return it("tokenises HTML tags with attributes that have expressions", function() { + const {tokens} = grammar.tokenizeLine("
@handleClick(e)}>"); + expect(tokens[0]).toEqual({value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']}); + expect(tokens[1]).toEqual({value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + expect(tokens[3]).toEqual({value: 'on-click', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ]}); + expect(tokens[4]).toEqual({value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ]}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.brace.curly.coffee']}); + expect(tokens[6]).toEqual({value: '(', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.begin.bracket.round.coffee' ]}); + expect(tokens[7]).toEqual({value: 'e', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'variable.parameter.function.coffee' ]}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.end.bracket.round.coffee' ]}); + expect(tokens[9]).toEqual({value: '->', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'storage.type.function.coffee' ]}); + expect(tokens[10]).toEqual({value: '@', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'variable.other.readwrite.instance.coffee' ]}); + expect(tokens[11]).toEqual({value: 'handleClick', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee' ]}); + expect(tokens[12]).toEqual({value: '(', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee' ]}); + expect(tokens[13]).toEqual({value: 'e', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee' ]}); + expect(tokens[14]).toEqual({value: ')', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee' ]}); + expect(tokens[15]).toEqual({value: '}', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.brace.curly.coffee']}); + return expect(tokens[16]).toEqual({value: '>', scopes: ['source.coffee', 'meta.tag.coffee']}); + }); +}); + + return describe("firstLineMatch", function() { + it("recognises interpreter directives", function() { + let line; + const valid = `\ +#!/usr/sbin/coffee foo +#!/usr/bin/coffee foo=bar/ +#!/usr/sbin/coffee +#!/usr/sbin/coffee foo bar baz +#!/usr/bin/coffee perl +#!/usr/bin/coffee bin/perl +#!/usr/bin/coffee +#!/bin/coffee +#!/usr/bin/coffee --script=usr/bin +#! /usr/bin/env A=003 B=149 C=150 D=xzd E=base64 F=tar G=gz H=head I=tail coffee +#!\t/usr/bin/env --foo=bar coffee --quu=quux +#! /usr/bin/coffee +#!/usr/bin/env coffee\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +\x20#!/usr/sbin/coffee +\t#!/usr/sbin/coffee +#!/usr/bin/env-coffee/node-env/ +#!/usr/bin/env-coffee +#! /usr/bincoffee +#!\t/usr/bin/env --coffee=bar\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + + it("recognises Emacs modelines", function() { + let line; + const valid = `\ +#-*- coffee -*- +#-*- mode: Coffee -*- +/* -*-coffee-*- */ +// -*- Coffee -*- +/* -*- mode:Coffee -*- */ +// -*- font:bar;mode:Coffee -*- +// -*- font:bar;mode:Coffee;foo:bar; -*- +// -*-font:mode;mode:COFFEE-*- +// -*- foo:bar mode: coffee bar:baz -*- +" -*-foo:bar;mode:cOFFEE;bar:foo-*- "; +" -*-font-mode:foo;mode:coFFeE;foo-bar:quux-*-" +"-*-font:x;foo:bar; mode : Coffee; bar:foo;foooooo:baaaaar;fo:ba;-*-"; +"-*- font:x;foo : bar ; mode : Coffee ; bar : foo ; foooooo:baaaaar;fo:ba-*-";\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +/* --*coffee-*- */ +/* -*-- coffee -*- +/* -*- -- Coffee -*- +/* -*- Coffee -;- -*- +// -*- freeCoffee -*- +// -*- Coffee; -*- +// -*- coffee-sugar -*- +/* -*- model:coffee -*- +/* -*- indent-mode:coffee -*- +// -*- font:mode;Coffee -*- +// -*- mode: -*- Coffee +// -*- mode: jfc-give-me-coffee -*- +// -*-font:mode;mode:coffee--*-\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + + return it("recognises Vim modelines", function() { + let line; + const valid = `\ +vim: se filetype=coffee: +# vim: se ft=coffee: +# vim: set ft=COFFEE: +# vim: set filetype=CoffEE: +# vim: ft=CoffEE +# vim: syntax=CoffEE +# vim: se syntax=CoffEE: +# ex: syntax=CoffEE +# vim:ft=coffee +# vim600: ft=coffee +# vim>600: set ft=coffee: +# vi:noai:sw=3 ts=6 ft=coffee +# vi::::::::::noai:::::::::::: ft=COFFEE +# vim:ts=4:sts=4:sw=4:noexpandtab:ft=cOfFeE +# vi:: noai : : : : sw =3 ts =6 ft =coFFEE +# vim: ts=4: pi sts=4: ft=cofFeE: noexpandtab: sw=4: +# vim: ts=4 sts=4: ft=coffee noexpandtab: +# vim:noexpandtab sts=4 ft=coffEE ts=4 +# vim:noexpandtab:ft=cOFFEe +# vim:ts=4:sts=4 ft=cofFeE:noexpandtab:\x20 +# vim:noexpandtab titlestring=hi\|there\\\\ ft=cOFFEe ts=4\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +ex: se filetype=coffee: +_vi: se filetype=coffee: + vi: se filetype=coffee +# vim set ft=coffee +# vim: soft=coffee +# vim: clean-syntax=coffee: +# vim set ft=coffee: +# vim: setft=coffee: +# vim: se ft=coffee backupdir=tmp +# vim: set ft=coffee set cmdheight=1 +# vim:noexpandtab sts:4 ft:coffee ts:4 +# vim:noexpandtab titlestring=hi\\|there\\ ft=coffee ts=4 +# vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=coffee ts=4\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + }); +}); diff --git a/packages/language-csharp/spec/grammar-spec.js b/packages/language-csharp/spec/grammar-spec.js new file mode 100644 index 0000000000..b81fbfa077 --- /dev/null +++ b/packages/language-csharp/spec/grammar-spec.js @@ -0,0 +1,21 @@ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +describe("Language C# package", function() { + + beforeEach(() => waitsForPromise(() => atom.packages.activatePackage("language-csharp"))); + + describe("C# Script grammar", () => it("parses the grammar", function() { + const grammar = atom.grammars.grammarForScopeName("source.csx"); + expect(grammar).toBeDefined(); + return expect(grammar.scopeName).toBe("source.csx"); + })); + + return describe("C# Cake grammar", () => it("parses the grammar", function() { + const grammar = atom.grammars.grammarForScopeName("source.cake"); + expect(grammar).toBeDefined(); + return expect(grammar.scopeName).toBe("source.cake"); + })); +}); diff --git a/packages/language-css/spec/css-spec.js b/packages/language-css/spec/css-spec.js new file mode 100644 index 0000000000..c092ee0070 --- /dev/null +++ b/packages/language-css/spec/css-spec.js @@ -0,0 +1,3954 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +describe('CSS grammar', function() { + let grammar = null; + + beforeEach(function() { + atom.config.set('core.useTreeSitterParsers', false); + + waitsForPromise(() => atom.packages.activatePackage('language-css')); + + return runs(() => grammar = atom.grammars.grammarForScopeName('source.css')); + }); + + it('parses the grammar', function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe('source.css'); + }); + + describe('selectors', function() { + it('tokenizes type selectors', function() { + const {tokens} = grammar.tokenizeLine('p {}'); + return expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + }); + + it('tokenizes the universal selector', function() { + const {tokens} = grammar.tokenizeLine('*'); + return expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + }); + + it('tokenises combinators', function() { + const {tokens} = grammar.tokenizeLine('a > b + * ~ :not(.nah)'); + expect(tokens[2]).toEqual({value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(tokens[6]).toEqual({value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + return expect(tokens[10]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + }); + + it('highlights deprecated combinators', function() { + const {tokens} = grammar.tokenizeLine('.sooo /deep/ >>>_.>>>'); + expect(tokens[3]).toEqual({value: '/deep/', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); + return expect(tokens[5]).toEqual({value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); + }); + + it('tokenizes complex selectors', function() { + const {tokens} = grammar.tokenizeLine('[disabled], [disabled] + p'); + expect(tokens[0]).toEqual({value: '[', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.begin.bracket.square.css"]}); + expect(tokens[1]).toEqual({value: 'disabled', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "entity.other.attribute-name.css"]}); + expect(tokens[2]).toEqual({value: ']', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.end.bracket.square.css"]}); + expect(tokens[3]).toEqual({value: ',', scopes: ["source.css", "meta.selector.css", "punctuation.separator.list.comma.css"]}); + expect(tokens[5]).toEqual({value: '[', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.begin.bracket.square.css"]}); + expect(tokens[6]).toEqual({value: 'disabled', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "entity.other.attribute-name.css"]}); + expect(tokens[7]).toEqual({value: ']', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.end.bracket.square.css"]}); + expect(tokens[9]).toEqual({value: '+', scopes: ["source.css", "meta.selector.css", "keyword.operator.combinator.css"]}); + expect(tokens[11]).toEqual({value: 'p', scopes: ["source.css", "meta.selector.css", "entity.name.tag.css"]}); + + const lines = grammar.tokenizeLines(`\ +[disabled]:not(:first-child)::before:hover + ~ div.object + + #id.thing:hover > strong ~ p::before, +a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], +*>em.i.ly[data-name|="Life"] { }\ +` + ); + expect(lines[0][0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(lines[0][1]).toEqual({value: 'disabled', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(lines[0][2]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(lines[0][3]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[0][4]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[0][5]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[0][6]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[0][7]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[0][8]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[0][9]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + expect(lines[0][10]).toEqual({value: 'before', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(lines[0][11]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[0][12]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[1][1]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(lines[1][3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[1][4]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(lines[1][5]).toEqual({value: 'object', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(lines[2][1]).toEqual({value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(lines[2][3]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + expect(lines[2][4]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(lines[2][5]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(lines[2][6]).toEqual({value: 'thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(lines[2][7]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[2][8]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[2][10]).toEqual({value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(lines[2][12]).toEqual({value: 'strong', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[2][14]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(lines[2][16]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[2][17]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + expect(lines[2][18]).toEqual({value: 'before', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(lines[2][19]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); + expect(lines[3][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[3][1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[3][2]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'invalid.illegal.colon.css']}); + expect(lines[3][3]).toEqual({value: 'last-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[3][4]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); + expect(lines[3][5]).toEqual({value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[3][6]).toEqual({value: 'Comment', scopes: ['source.css', 'comment.block.css']}); + expect(lines[3][7]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[3][8]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + expect(lines[3][9]).toEqual({value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(lines[3][11]).toEqual({value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(lines[3][13]).toEqual({value: 'html', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[3][14]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(lines[3][15]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(lines[3][16]).toEqual({value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(lines[3][17]).toEqual({value: 'en-AU', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + expect(lines[3][18]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(lines[3][19]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); + expect(lines[4][0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(lines[4][1]).toEqual({value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(lines[4][2]).toEqual({value: 'em', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[4][3]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(lines[4][4]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(lines[4][5]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(lines[4][6]).toEqual({value: 'ly', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(lines[4][7]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(lines[4][8]).toEqual({value: 'data-name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(lines[4][9]).toEqual({value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(lines[4][10]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[4][11]).toEqual({value: 'Life', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(lines[4][12]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[4][13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(lines[4][15]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(lines[4][17]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + describe('custom elements (as type selectors)', function() { + it('only tokenizes identifiers beginning with [a-z]', function() { + const {tokens} = grammar.tokenizeLine('pearl-1941 1941-pearl -pearl-1941'); + expect(tokens[0]).toEqual({value: 'pearl-1941', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + return expect(tokens[1]).toEqual({value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css']}); + }); + + it('tokenizes custom elements containing non-ASCII letters', function() { + const {tokens} = grammar.tokenizeLine('pokémon-ピカチュウ'); + return expect(tokens[0]).toEqual({value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + }); + + it('does not tokenize identifiers containing [A-Z]', function() { + const {tokens} = grammar.tokenizeLine('Basecamp-schedule basecamp-Schedule'); + return expect(tokens[0]).toEqual({value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css']}); + }); + + it('does not tokenize identifiers containing no hyphens', function() { + const {tokens} = grammar.tokenizeLine('halo_night'); + return expect(tokens[0]).toEqual({value: 'halo_night', scopes: ['source.css', 'meta.selector.css']}); + }); + + it('does not tokenise identifiers following an @ symbol', function() { + const {tokens} = grammar.tokenizeLine('@some-weird-new-feature'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); + return expect(tokens[1]).toEqual({value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + }); + + return it('does not tokenise identifiers in unfamiliar functions', function() { + const {tokens} = grammar.tokenizeLine('some-edgy-new-function()'); + expect(tokens[0]).toEqual({value: 'some-edgy-new-function(', scopes: ['source.css', 'meta.selector.css']}); + return expect(tokens[1]).toEqual({value: ')', scopes: ['source.css']}); + }); + }); + + describe('attribute selectors', function() { + it('tokenizes attribute selectors without values', function() { + const {tokens} = grammar.tokenizeLine('[title]'); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[1]).toEqual({value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + return expect(tokens[2]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenizes attribute selectors with identifier values', function() { + const {tokens} = grammar.tokenizeLine('[hreflang|=fr]'); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[1]).toEqual({value: 'hreflang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[2]).toEqual({value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[3]).toEqual({value: 'fr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + return expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenizes attribute selectors with string values', function() { + const {tokens} = grammar.tokenizeLine('[href^="http://www.w3.org/"]'); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[1]).toEqual({value: 'href', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[2]).toEqual({value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[4]).toEqual({value: 'http://www.w3.org/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenizes CSS qualified attribute names with wildcard prefix', function() { + const {tokens} = grammar.tokenizeLine('[*|title]'); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[1]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[2]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); + expect(tokens[3]).toEqual({value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + return expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenizes CSS qualified attribute names with namespace prefix', function() { + const {tokens} = grammar.tokenizeLine('[marvel|origin=radiation]'); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[1]).toEqual({value: 'marvel', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[2]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); + expect(tokens[3]).toEqual({value: 'origin', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[4]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[5]).toEqual({value: 'radiation', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenizes CSS qualified attribute names without namespace prefix', function() { + const {tokens} = grammar.tokenizeLine('[|data-hp="75"]'); + expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); + expect(tokens[2]).toEqual({value: 'data-hp', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[3]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[5]).toEqual({value: '75', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + return expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenises compound ID/attribute selectors', function() { + let {tokens} = grammar.tokenizeLine('#div[id="0"]{ }'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[2]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[3]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[8]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + + ({tokens} = grammar.tokenizeLine('.bar#div[id="0"]')); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'bar', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[2]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + expect(tokens[3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[4]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + return expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + }); + + it('tokenises compound class/attribute selectors', function() { + let {tokens} = grammar.tokenizeLine('.div[id="0"]{ }'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[2]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[3]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[8]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + + ({tokens} = grammar.tokenizeLine('#bar.div[id]')); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'bar', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[2]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[4]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('allows whitespace to be inserted between tokens', function() { + const {tokens} = grammar.tokenizeLine('span[ er|lang |= "%%" ]'); + expect(tokens[1]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[3]).toEqual({value: 'er', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[4]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); + expect(tokens[5]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[7]).toEqual({value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[8]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[9]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[10]).toEqual({value: '%%', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(tokens[11]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[12]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + return expect(tokens[13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenises escape sequences inside attribute selectors', function() { + const {tokens} = grammar.tokenizeLine('a[name\\[0\\]="value"]'); + expect(tokens[2]).toEqual({value: 'name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[3]).toEqual({value: '\\[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); + expect(tokens[4]).toEqual({value: '0', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[5]).toEqual({value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); + expect(tokens[6]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + return expect(tokens[10]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenises escape sequences inside namespace prefixes', function() { + const {tokens} = grammar.tokenizeLine('a[name\\ space|Get\\ It\\?="kek"]'); + expect(tokens[2]).toEqual({value: 'name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[3]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css', 'constant.character.escape.css']}); + expect(tokens[4]).toEqual({value: 'space', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[5]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); + expect(tokens[6]).toEqual({value: 'Get', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[7]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); + expect(tokens[8]).toEqual({value: 'It', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[9]).toEqual({value: '\\?', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); + expect(tokens[10]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + return expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenises comments inside attribute selectors', function() { + const {tokens} = grammar.tokenizeLine('span[/*]*/lang]'); + expect(tokens[0]).toEqual({value: 'span', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[5]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenises quoted strings in attribute selectors', function() { + let {tokens} = grammar.tokenizeLine('a[href^="#"] a[href^= "#"] a[href^="#" ]'); + expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[5]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[12]).toEqual({value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[13]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[14]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[15]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(tokens[16]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[23]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[24]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(tokens[25]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[26]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[27]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + + ({tokens} = grammar.tokenizeLine("a[href^='#'] a[href^= '#'] a[href^='#' ]")); + expect(tokens[4]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[5]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css']}); + expect(tokens[6]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[12]).toEqual({value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[13]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[14]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[15]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css']}); + expect(tokens[16]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[23]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[24]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css']}); + expect(tokens[25]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[26]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + return expect(tokens[27]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenises unquoted strings in attribute selectors', function() { + let {tokens} = grammar.tokenizeLine('span[class~=Java]'); + expect(tokens[3]).toEqual({value: '~=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[4]).toEqual({value: 'Java', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + expect(tokens[5]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + + ({tokens} = grammar.tokenizeLine('span[class^= 0xDEADCAFE=|~BEEFBABE ]')); + expect(tokens[3]).toEqual({value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[5]).toEqual({value: '0xDEADCAFE=|~BEEFBABE', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + return expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + it('tokenises escape sequences in unquoted strings', function() { + const {tokens} = grammar.tokenizeLine('a[name\\[0\\]=a\\BAD\\AF\\]a\\ i] {}'); + expect(tokens[6]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[7]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + expect(tokens[8]).toEqual({value: '\\BAD', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[9]).toEqual({value: '\\AF', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[10]).toEqual({value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css']}); + expect(tokens[11]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + expect(tokens[12]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css']}); + expect(tokens[13]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('tokenises the ignore-case modifier at the end of a selector', function() { + const {tokens} = grammar.tokenizeLine('a[attr=val i] a[attr="val" i] a[attr=\'val\'I] a[val^= \'"\'i] a[attr= i] a[attr= i i]'); + expect(tokens[6]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); + expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[16]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[17]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); + expect(tokens[26]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[27]).toEqual({value: 'I', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); + expect(tokens[28]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[34]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[35]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[36]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css']}); + expect(tokens[37]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[38]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); + expect(tokens[39]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[44]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[45]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[46]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + expect(tokens[47]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[52]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(tokens[53]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[54]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); + expect(tokens[55]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(tokens[56]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); + return expect(tokens[57]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + + return it('tokenises attribute selectors spanning multiple lines', function() { + let lines = grammar.tokenizeLines(`\ +span[ + \\x20{2} + ns|lang/**/ + |= +"pt"]\ +` + ); + expect(lines[0][0]).toEqual({value: 'span', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[0][1]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(lines[1][0]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); + expect(lines[2][1]).toEqual({value: 'ns', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); + expect(lines[2][2]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); + expect(lines[2][3]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(lines[2][4]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][5]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[3][1]).toEqual({value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(lines[4][0]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[4][1]).toEqual({value: 'pt', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(lines[4][2]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[4][3]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + + lines = grammar.tokenizeLines(`\ +span[/*=== +==|span[/*} +====*/*|lang/*]=*/~=/*"|"*/"en-AU"/* + | +*/ +i]\ +` + ); + expect(lines[0][2]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][3]).toEqual({value: '===', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); + expect(lines[1][0]).toEqual({value: '==|span[/*}', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); + expect(lines[2][0]).toEqual({value: '====', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); + expect(lines[2][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][2]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); + expect(lines[2][3]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); + expect(lines[2][4]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(lines[2][5]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][6]).toEqual({value: ']=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); + expect(lines[2][7]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][8]).toEqual({value: '~=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(lines[2][9]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][10]).toEqual({value: '"|"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); + expect(lines[2][11]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][12]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[2][13]).toEqual({value: 'en-AU', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(lines[2][14]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[2][15]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[3][0]).toEqual({value: ' |', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); + expect(lines[4][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[5][0]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); + return expect(lines[5][1]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + }); + }); + + describe('class selectors', function() { + it('tokenizes class selectors containing non-ASCII letters', function() { + let {tokens} = grammar.tokenizeLine('.étendard'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'étendard', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + + ({tokens} = grammar.tokenizeLine('.スポンサー')); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + return expect(tokens[1]).toEqual({value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + }); + + it('tokenizes a class selector consisting of two hypens', function() { + const {tokens} = grammar.tokenizeLine('.--'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + return expect(tokens[1]).toEqual({value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + }); + + it('tokenizes class selectors consisting of one (valid) character', function() { + const {tokens} = grammar.tokenizeLine('._'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + return expect(tokens[1]).toEqual({value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + }); + + it('tokenises class selectors starting with an escape sequence', function() { + const {tokens} = grammar.tokenizeLine('.\\33\\44-model {'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[2]).toEqual({value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[3]).toEqual({value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + return expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('tokenises class selectors ending with an escape sequence', function() { + const {tokens} = grammar.tokenizeLine('.la\\{tex\\} {'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css']}); + expect(tokens[3]).toEqual({value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[4]).toEqual({value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css']}); + return expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('marks a class invalid if it contains unescaped ASCII punctuation or symbols other than "-" and "_"', function() { + const {tokens} = grammar.tokenizeLine('.B&W{'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'B&W', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('marks a class invalid if it starts with ASCII digits ([0-9])', function() { + const {tokens} = grammar.tokenizeLine('.666{'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('marks a class invalid if it starts with "-" followed by ASCII digits', function() { + const {tokens} = grammar.tokenizeLine('.-911-{'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + return it('marks a class invalid if it consists of only one hyphen', function() { + const {tokens} = grammar.tokenizeLine('.-{'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + }); + + describe('id selectors', function() { + it('tokenizes id selectors consisting of ASCII letters', function() { + const {tokens} = grammar.tokenizeLine('#unicorn'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + return expect(tokens[1]).toEqual({value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + }); + + it('tokenizes id selectors containing non-ASCII letters', function() { + const {tokens} = grammar.tokenizeLine('#洪荒之力'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + return expect(tokens[1]).toEqual({value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + }); + + it('tokenizes id selectors containing [0-9], "-", or "_"', function() { + const {tokens} = grammar.tokenizeLine('#_zer0-day'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + return expect(tokens[1]).toEqual({value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + }); + + it('tokenizes id selectors beginning with two hyphens', function() { + const {tokens} = grammar.tokenizeLine('#--d3bug--'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + return expect(tokens[1]).toEqual({value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + }); + + it('marks an id invalid if it contains ASCII punctuation or symbols other than "-" and "_"', function() { + const {tokens} = grammar.tokenizeLine('#sort!{'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'sort!', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('marks an id invalid if it starts with ASCII digits ([0-9])', function() { + const {tokens} = grammar.tokenizeLine('#666{'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('marks an id invalid if it starts with "-" followed by ASCII digits', function() { + const {tokens} = grammar.tokenizeLine('#-911-{'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('marks an id invalid if it consists of one hyphen only', function() { + const {tokens} = grammar.tokenizeLine('#-{'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('tokenises ID selectors starting with an escape sequence', function() { + const {tokens} = grammar.tokenizeLine('#\\33\\44-model {'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[2]).toEqual({value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[3]).toEqual({value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + return expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + return it('tokenises ID selectors ending with an escape sequence', function() { + const {tokens} = grammar.tokenizeLine('#la\\{tex\\} {'); + expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css']}); + expect(tokens[3]).toEqual({value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[4]).toEqual({value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css']}); + return expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + }); + + describe('namespace prefixes', function() { + it('tokenises arbitrary namespace prefixes', function() { + const {tokens} = grammar.tokenizeLine('foo|h1 { }'); + expect(tokens[0]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); + expect(tokens[2]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('tokenises anonymous namespace prefixes', function() { + let {tokens} = grammar.tokenizeLine('*|abbr {}'); + expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); + expect(tokens[2]).toEqual({value: 'abbr', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('*|* {}')); + expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); + expect(tokens[2]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('foo|* { }')); + expect(tokens[0]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); + expect(tokens[2]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('|[svg|attr=name]{}')); + expect(tokens[0]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); + expect(tokens[1]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(tokens[2]).toEqual({value: 'svg', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); + expect(tokens[3]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); + return expect(tokens[4]).toEqual({value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + }); + + it('tokenises the "no-namespace" prefix', function() { + const {tokens} = grammar.tokenizeLine('|h1 { }'); + expect(tokens[0]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); + expect(tokens[1]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[3]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + return it("doesn't tokenise prefixes without a selector", function() { + let {tokens} = grammar.tokenizeLine('*| { }'); + expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[3]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('*|{ }')); + expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + }); + + describe('at-rules', function() { + describe('@charset', function() { + // NB: \A won't match if "tokenizeLine" is used; "tokenizeLines" is used here to circumvent this limitation + it('tokenises @charset rules at the start of a file', function() { + let lines = grammar.tokenizeLines('@charset "US-ASCII";'); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css']}); + expect(lines[0][2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css']}); + expect(lines[0][3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[0][4]).toEqual({value: 'US-ASCII', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css']}); + expect(lines[0][5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[0][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + + lines = grammar.tokenizeLines('/* Not the first line */\n@charset "UTF-8";'); + expect(lines[0][0]).toEqual({value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][1]).toEqual({value: ' Not the first line ', scopes: ['source.css', 'comment.block.css']}); + expect(lines[0][2]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[1][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); + return expect(lines[1][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + }); + + return it('highlights invalid @charset statements', function() { + let lines = grammar.tokenizeLines(" @charset 'US-ASCII';"); + expect(lines[0][0]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.leading-whitespace.charset.css']}); + expect(lines[0][1]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][2]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css']}); + expect(lines[0][4]).toEqual({value: "'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-double-quoted.charset.css']}); + expect(lines[0][5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + + lines = grammar.tokenizeLines('@charset "iso-8859-15";'); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css']}); + expect(lines[0][2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.whitespace.charset.css']}); + expect(lines[0][3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[0][4]).toEqual({value: 'iso-8859-15', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css']}); + expect(lines[0][5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[0][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + + lines = grammar.tokenizeLines('@charset"US-ASCII";'); + expect(lines[0][0]).toEqual({value: '@charset"US-ASCII"', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.no-whitespace.charset.css']}); + expect(lines[0][1]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + + lines = grammar.tokenizeLines('@charset "UTF-8" ;'); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css']}); + expect(lines[0][2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css']}); + expect(lines[0][3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[0][4]).toEqual({value: 'UTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css']}); + expect(lines[0][5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[0][6]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unexpected-characters.charset.css']}); + expect(lines[0][7]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + + lines = grammar.tokenizeLines('@charset "WTF-8" /* Nope */ ;'); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css']}); + expect(lines[0][2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css']}); + expect(lines[0][3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[0][4]).toEqual({value: 'WTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css']}); + expect(lines[0][5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[0][6]).toEqual({value: ' /* Nope */ ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unexpected-characters.charset.css']}); + expect(lines[0][7]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + + lines = grammar.tokenizeLines('@charset "UTF-8'); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css']}); + expect(lines[0][2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css']}); + expect(lines[0][3]).toEqual({value: '"UTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unclosed-string.charset.css']}); + + lines = grammar.tokenizeLines("@CHARSET 'US-ASCII';"); + expect(lines[0][0]).toEqual({value: '@CHARSET', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-lowercase.charset.css']}); + expect(lines[0][1]).toEqual({value: " 'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css']}); + return expect(lines[0][2]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + }); + }); + + describe('@import', function() { + it('tokenises @import statements', function() { + let {tokens} = grammar.tokenizeLine('@import url("file.css");'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[3]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[6]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine('@import "file.css";')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[4]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine("@import 'file.css';")); + expect(tokens[3]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[4]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css']}); + return expect(tokens[5]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + }); + + it("doesn't let injected comments impact parameter matching", function() { + let {tokens} = grammar.tokenizeLine('@import /* url("name"); */ "1.css";'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[3]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[4]).toEqual({value: ' url("name"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); + expect(tokens[5]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[8]).toEqual({value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); + expect(tokens[9]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine('@import/* Comment */"2.css";')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: ' Comment ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[6]).toEqual({value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + return expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + }); + + it('correctly handles word boundaries', function() { + let {tokens} = grammar.tokenizeLine('@import"file.css";'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[3]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); + expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine('@import-file.css;')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import-file', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + expect(tokens[2]).toEqual({value: '.css', scopes: ['source.css', 'meta.at-rule.header.css']}); + return expect(tokens[3]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css']}); + }); + + it('matches a URL that starts on the next line', function() { + const lines = grammar.tokenizeLines('@import\nurl("file.css");'); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(lines[0][2]).toEqual({value: '', scopes: ['source.css', 'meta.at-rule.import.css']}); + expect(lines[1][0]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(lines[1][1]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][2]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[1][3]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css']}); + expect(lines[1][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[1][5]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + }); + + it('matches comments inside query lists', function() { + const {tokens} = grammar.tokenizeLine('@import url("1.css") print /* url(";"); */ all;'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[3]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[6]).toEqual({value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[10]).toEqual({value: 'print', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css']}); + expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[13]).toEqual({value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); + expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[16]).toEqual({value: 'all', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css']}); + return expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + }); + + it('highlights deprecated media types', function() { + const {tokens} = grammar.tokenizeLine('@import "astral.css" projection;'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[4]).toEqual({value: 'astral.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[7]).toEqual({value: 'projection', scopes: ['source.css', 'meta.at-rule.import.css', 'invalid.deprecated.constant.media.css']}); + return expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + }); + + return it('highlights media features in query lists', function() { + const {tokens} = grammar.tokenizeLine('@import url(\'landscape.css\') screen and (orientation:landscape);'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[3]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[5]).toEqual({value: '\'', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[6]).toEqual({value: 'landscape.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css']}); + expect(tokens[7]).toEqual({value: '\'', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[10]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css']}); + expect(tokens[12]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.operator.logical.and.media.css']}); + expect(tokens[14]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[15]).toEqual({value: 'orientation', scopes: ['source.css', 'meta.at-rule.import.css', 'support.type.property-name.media.css']}); + expect(tokens[16]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.separator.key-value.css']}); + expect(tokens[17]).toEqual({value: 'landscape', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.property-value.css']}); + expect(tokens[18]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + return expect(tokens[19]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + }); + }); + + describe('@media', function() { + it('tokenises @media keywords correctly', function() { + let {tokens} = grammar.tokenizeLine('@media(max-width: 37.5em) { }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[2]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[3]).toEqual({value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(tokens[7]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[9]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[10]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + expect(tokens[12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('@media not print and (max-width: 37.5em){ }')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.not.media.css']}); + expect(tokens[5]).toEqual({value: 'print', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(tokens[7]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css']}); + expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[10]).toEqual({value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(tokens[11]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[13]).toEqual({value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(tokens[14]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + return expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + }); + + it('highlights deprecated media types', function() { + const {tokens} = grammar.tokenizeLine('@media (max-device-width: 2px){ }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: 'max-device-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[10]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + return expect(tokens[12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + }); + + it('highlights vendored media features', function() { + let {tokens} = grammar.tokenizeLine('@media (-webkit-foo: bar){ b{ } }'); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: '-webkit-foo', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: ' bar', scopes: ['source.css', 'meta.at-rule.media.header.css']}); + expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('@media screen and (-ms-high-contrast:black-on-white){ }')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(tokens[5]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '-ms-high-contrast', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); + expect(tokens[9]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[10]).toEqual({value: 'black-on-white', scopes: ['source.css', 'meta.at-rule.media.header.css']}); + expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[12]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + expect(tokens[14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('@media (_moz-a:b){}')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: '_moz-a', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: 'b', scopes: ['source.css', 'meta.at-rule.media.header.css']}); + expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + + ({tokens} = grammar.tokenizeLine('@media (-hp-foo:bar){}')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: '-hp-foo', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: 'bar', scopes: ['source.css', 'meta.at-rule.media.header.css']}); + expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + + ({tokens} = grammar.tokenizeLine('@media (mso-page-size:wide){}')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: 'mso-page-size', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: 'wide', scopes: ['source.css', 'meta.at-rule.media.header.css']}); + return expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + }); + + it('tokenises @media immediately following a closing brace', function() { + let {tokens} = grammar.tokenizeLine('h1 { }@media only screen { } h2 { }'); + expect(tokens[0]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[6]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[8]).toEqual({value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css']}); + expect(tokens[10]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(tokens[12]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + expect(tokens[14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[16]).toEqual({value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[18]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[20]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('h1 { }@media only screen { }h2 { }')); + expect(tokens[0]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[6]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[8]).toEqual({value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css']}); + expect(tokens[10]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(tokens[12]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + expect(tokens[14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[15]).toEqual({value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[17]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('tokenises level 4 media-query syntax', function() { + const lines = grammar.tokenizeLines(`\ +@media (min-width >= 0px) + and (max-width <= 400) + and (min-height > 400) + and (max-height < 200)\ +` + ); + expect(lines[0][6]).toEqual({value: '>=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); + expect(lines[1][6]).toEqual({value: '<=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); + expect(lines[2][6]).toEqual({value: '>', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); + return expect(lines[3][6]).toEqual({value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); + }); + + it('tokenises comments between media types', function() { + const {tokens} = grammar.tokenizeLine('@media/* */only/* */screen/* */and (min-width:1100px){}'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[5]).toEqual({value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css']}); + expect(tokens[6]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[8]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[9]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(tokens[10]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[12]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[13]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css']}); + expect(tokens[15]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[16]).toEqual({value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(tokens[17]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[18]).toEqual({value: '1100', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(tokens[19]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[20]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[21]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + return expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + }); + + return it('tokenises comments between media features', function() { + const {tokens} = grammar.tokenizeLine('@media/*=*/(max-width:/**/37.5em)/*=*/and/*=*/(/*=*/min-height/*:*/:/*=*/1.2em/*;*/){}'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[6]).toEqual({value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(tokens[7]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[8]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[9]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[10]).toEqual({value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(tokens[11]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[13]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[14]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(tokens[15]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[16]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css']}); + expect(tokens[17]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[18]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(tokens[19]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[20]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[21]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[22]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(tokens[23]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[24]).toEqual({value: 'min-height', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(tokens[25]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[26]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(tokens[27]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[28]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[29]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[30]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(tokens[31]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[32]).toEqual({value: '1.2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(tokens[33]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(tokens[34]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[35]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(tokens[36]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[37]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[38]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + return expect(tokens[39]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + }); + }); + + it('matches media queries across lines', function() { + const lines = grammar.tokenizeLines(`\ +@media only screen and (min-width : /* 40 */ + 320px), + not print and (max-width: 480px) /* kek */ and (-webkit-min-device-pixel-ratio /*:*/ : 2), +only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-ratio: 2) { }\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(lines[0][3]).toEqual({value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css']}); + expect(lines[0][5]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(lines[0][7]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css']}); + expect(lines[0][9]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(lines[0][10]).toEqual({value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(lines[0][12]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(lines[0][14]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][15]).toEqual({value: ' 40 ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(lines[0][16]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[1][1]).toEqual({value: '320', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(lines[1][2]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[1][3]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(lines[1][4]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css']}); + expect(lines[2][1]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.not.media.css']}); + expect(lines[2][3]).toEqual({value: 'print', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(lines[2][5]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css']}); + expect(lines[2][7]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(lines[2][8]).toEqual({value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(lines[2][9]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][11]).toEqual({value: '480', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(lines[2][12]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[2][13]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(lines[2][15]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][16]).toEqual({value: ' kek ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(lines[2][17]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][19]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css']}); + expect(lines[2][21]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(lines[2][22]).toEqual({value: '-webkit-min-device-pixel-ratio', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); + expect(lines[2][24]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][25]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(lines[2][26]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][28]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][30]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(lines[2][31]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(lines[2][32]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css']}); + expect(lines[3][0]).toEqual({value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css']}); + expect(lines[3][2]).toEqual({value: 'speech', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(lines[3][4]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css']}); + expect(lines[3][6]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(lines[3][7]).toEqual({value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(lines[3][8]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(lines[3][10]).toEqual({value: '10', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(lines[3][11]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[3][12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(lines[3][13]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css']}); + expect(lines[3][15]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[3][16]).toEqual({value: ' wat ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(lines[3][17]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[3][19]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(lines[3][20]).toEqual({value: '-webkit-min-device-pixel-ratio', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); + expect(lines[3][21]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(lines[3][23]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(lines[3][24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(lines[3][26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + return expect(lines[3][28]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + }); + + it('highlights invalid commas', function() { + let {tokens} = grammar.tokenizeLine('@media , {}'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css']}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('@media , ,screen {}')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: ', ,', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css']}); + expect(tokens[4]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); + expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); + return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + }); + + it('allows spaces inside ratio values', function() { + const {tokens} = grammar.tokenizeLine('@media (min-aspect-ratio: 3 / 4) and (max-aspect-ratio: 20 / 17) {}'); + expect(tokens[7]).toEqual({value: '3', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); + expect(tokens[8]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); + expect(tokens[9]).toEqual({value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css']}); + expect(tokens[10]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); + expect(tokens[11]).toEqual({value: '4', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); + expect(tokens[20]).toEqual({value: '20', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); + expect(tokens[21]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); + expect(tokens[22]).toEqual({value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css']}); + expect(tokens[23]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); + return expect(tokens[24]).toEqual({value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); + }); + + describe('@keyframes', function() { + it('tokenises keyframe lists correctly', function() { + const lines = grammar.tokenizeLines(`\ +@keyframes important1 { + from { margin-top: 50px; + margin-bottom: 100px } + 50% { margin-top: 150px !important; } /* Ignored */ + to { margin-top: 100px; } +}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css']}); + expect(lines[0][3]).toEqual({value: 'important1', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + expect(lines[0][4]).toEqual({value: ' ', scopes: ['source.css']}); + expect(lines[0][5]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css']}); + expect(lines[1][1]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + expect(lines[1][3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[1][5]).toEqual({value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][6]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[1][8]).toEqual({value: '50', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[1][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[1][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[2][1]).toEqual({value: 'margin-bottom', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[2][2]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][4]).toEqual({value: '100', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[2][5]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[2][7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[3][1]).toEqual({value: '50%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); + expect(lines[3][3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[3][5]).toEqual({value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[3][6]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[3][8]).toEqual({value: '150', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[3][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[3][11]).toEqual({value: '!important', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'keyword.other.important.css']}); + expect(lines[3][12]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[3][14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[3][16]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[3][17]).toEqual({value: ' Ignored ', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css']}); + expect(lines[3][18]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[4][1]).toEqual({value: 'to', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + expect(lines[4][3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[4][5]).toEqual({value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[4][6]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[4][8]).toEqual({value: '100', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[4][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[4][12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + }); + + it('matches injected comments', function() { + const lines = grammar.tokenizeLines(`\ +@keyframes/*{*/___IDENT__/*} + { Nah { margin-top: 2em; } +*/{ from\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css']}); + expect(lines[0][2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css']}); + expect(lines[0][4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[0][5]).toEqual({value: '___IDENT__', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + expect(lines[0][6]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css']}); + expect(lines[1][0]).toEqual({value: ' { Nah { margin-top: 2em; }', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css']}); + expect(lines[2][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][1]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css']}); + return expect(lines[2][3]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + }); + + it('matches offset keywords case-insensitively', function() { + const {tokens} = grammar.tokenizeLine('@keyframes Give-them-both { fROm { } To {} }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css']}); + expect(tokens[3]).toEqual({value: 'Give-them-both', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: 'fROm', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + expect(tokens[9]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[11]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[13]).toEqual({value: 'To', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + expect(tokens[15]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[16]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + }); + + it('matches percentile offsets', function() { + const {tokens} = grammar.tokenizeLine('@keyframes identifier { -50.2% } @keyframes ident2 { .25%}'); + expect(tokens[7]).toEqual({value: '-50.2%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); + return expect(tokens[18]).toEqual({value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); + }); + + return it('highlights escape sequences inside identifiers', function() { + const {tokens} = grammar.tokenizeLine('@keyframes A\\1F602Z'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css']}); + expect(tokens[3]).toEqual({value: 'A', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + expect(tokens[4]).toEqual({value: '\\1F602', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css', 'constant.character.escape.codepoint.css']}); + return expect(tokens[5]).toEqual({value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + }); + }); + + describe('@supports', function() { + it('tokenises feature queries', function() { + const {tokens} = grammar.tokenizeLine('@supports (font-size: 1em) { }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.supports.header.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: 'font-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(tokens[7]).toEqual({value: '1', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[8]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(tokens[10]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[11]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + return expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + }); + + it('matches logical operators', function() { + const lines = grammar.tokenizeLines(`\ +@supports not (font-size: 1em){ } +@supports (font-size: 1em) and (font-size: 1em){ } +@supports (font-size: 1em) or (font-size: 1em){ }\ +` + ); + expect(lines[0][3]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css']}); + expect(lines[1][11]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css']}); + return expect(lines[2][11]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); + }); + + it('matches custom variables in feature queries', function() { + const {tokens} = grammar.tokenizeLine('@supports (--foo: green){}'); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: '--foo', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'variable.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(tokens[7]).toEqual({value: 'green', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); + return expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + }); + + it("doesn't mistake brackets in string literals for feature queries", function() { + const lines = grammar.tokenizeLines(`\ +@supports not ((tab-size:4) or (-moz-tab-size:4)){ + body::before{content: "Come on, Microsoft (Get it together already)…"; } +}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css']}); + expect(lines[0][3]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css']}); + expect(lines[0][7]).toEqual({value: 'tab-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[0][12]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'keyword.operator.logical.feature.or.css']}); + expect(lines[0][15]).toEqual({value: '-moz-tab-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); + expect(lines[0][20]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + expect(lines[1][1]).toEqual({value: 'body', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[1][2]).toEqual({value: '::', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + expect(lines[1][3]).toEqual({value: 'before', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(lines[1][4]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[1][5]).toEqual({value: 'content', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][6]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[1][8]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[1][9]).toEqual({value: 'Come on, Microsoft (Get it together already)…', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css']}); + expect(lines[1][10]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[1][11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[1][13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + }); + + it('tokenises multiple feature queries', function() { + const {tokens} = grammar.tokenizeLine('@supports (display:table-cell) or ((display:list-item) and (display:run-in)){'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: 'table-cell', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(tokens[9]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); + expect(tokens[11]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(tokens[12]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(tokens[13]).toEqual({value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[14]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(tokens[15]).toEqual({value: 'list-item', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[16]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(tokens[18]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'keyword.operator.logical.feature.and.css']}); + expect(tokens[20]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(tokens[21]).toEqual({value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[22]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(tokens[23]).toEqual({value: 'run-in', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(tokens[25]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + return expect(tokens[26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + }); + + it('embeds rulesets and other at-rules', function() { + const lines = grammar.tokenizeLines(`\ +@supports (animation-name: test) { + #node { + animation-name: test; + } + body > header[data-name="attr"] ~ *:not(:first-child){ + content: "😂👌" + } + @keyframes important1 { + from { + margin-top: 50px; + margin-bottom: 100px + } + 50% { margin-top: 150px !important; } /* Ignored */ + to { margin-top: 100px; } + } +}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css']}); + expect(lines[0][3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(lines[0][4]).toEqual({value: 'animation-name', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[0][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(lines[0][7]).toEqual({value: 'test', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css']}); + expect(lines[0][8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(lines[0][10]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + expect(lines[1][1]).toEqual({value: '#', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); + expect(lines[1][2]).toEqual({value: 'node', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(lines[1][4]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[2][1]).toEqual({value: 'animation-name', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[2][2]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][4]).toEqual({value: 'test', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(lines[2][5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[3][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][1]).toEqual({value: 'body', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[4][3]).toEqual({value: '>', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(lines[4][5]).toEqual({value: 'header', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[4][6]).toEqual({value: '[', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); + expect(lines[4][7]).toEqual({value: 'data-name', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(lines[4][8]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); + expect(lines[4][9]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[4][10]).toEqual({value: 'attr', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); + expect(lines[4][11]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[4][12]).toEqual({value: ']', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(lines[4][14]).toEqual({value: '~', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(lines[4][16]).toEqual({value: '*', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(lines[4][17]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[4][18]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[4][19]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[4][20]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[4][21]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[4][22]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[4][23]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[5][1]).toEqual({value: 'content', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[5][2]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[5][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[5][5]).toEqual({value: '😂👌', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css']}); + expect(lines[5][6]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[6][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[7][1]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css']}); + expect(lines[7][2]).toEqual({value: 'keyframes', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css']}); + expect(lines[7][4]).toEqual({value: 'important1', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + expect(lines[7][6]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css']}); + expect(lines[8][1]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + expect(lines[8][3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[9][1]).toEqual({value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[9][2]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[9][4]).toEqual({value: '50', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[9][5]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[9][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[10][1]).toEqual({value: 'margin-bottom', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[10][2]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[10][4]).toEqual({value: '100', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[10][5]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[11][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[12][1]).toEqual({value: '50%', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); + expect(lines[12][3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[12][5]).toEqual({value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[12][6]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[12][8]).toEqual({value: '150', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[12][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[12][11]).toEqual({value: '!important', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'keyword.other.important.css']}); + expect(lines[12][12]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[12][14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[12][16]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[12][17]).toEqual({value: ' Ignored ', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css']}); + expect(lines[12][18]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[13][1]).toEqual({value: 'to', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + expect(lines[13][3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[13][5]).toEqual({value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[13][6]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[13][8]).toEqual({value: '100', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[13][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[13][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[13][12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[14][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + return expect(lines[15][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + }); + + it('matches injected comments', function() { + // NB: This particular example actually isn't valid @supports + // syntax; it's just for stress-testing boundary-matching. + const lines = grammar.tokenizeLines(`\ +@supports/*===*/not/*==****************| +==*/(display:table-cell)/*============*/ and (display: list-item)/*}*/{}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css']}); + expect(lines[0][2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][3]).toEqual({value: '===', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css']}); + expect(lines[0][4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[0][5]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css']}); + expect(lines[0][6]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][7]).toEqual({value: '==****************|', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css']}); + expect(lines[1][0]).toEqual({value: '==', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css']}); + expect(lines[1][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[1][2]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(lines[1][3]).toEqual({value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][4]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(lines[1][5]).toEqual({value: 'table-cell', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[1][6]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(lines[1][7]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[1][8]).toEqual({value: '============', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css']}); + expect(lines[1][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[1][11]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css']}); + expect(lines[1][13]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(lines[1][19]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[1][20]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css']}); + expect(lines[1][21]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[1][22]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + return expect(lines[1][23]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + }); + + return it('matches feature queries across multiple lines', function() { + const lines = grammar.tokenizeLines(`\ +@supports + (box-shadow: 0 0 2px rgba(0,0,0,.5) inset) or + (-moz-box-shadow: 0 0 2px black inset) or + (-webkit-box-shadow: 0 0 2px black inset) or + (-o-box-shadow: 0 0 2px black inset) +{ .noticebox { } }\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css']}); + expect(lines[1][1]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(lines[1][2]).toEqual({value: 'box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][3]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(lines[1][5]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[1][7]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[1][9]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[1][10]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[1][12]).toEqual({value: 'rgba', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[1][13]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][14]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[1][15]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(lines[1][16]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[1][17]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(lines[1][18]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[1][19]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(lines[1][20]).toEqual({value: '.5', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[1][21]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[1][23]).toEqual({value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[1][24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(lines[1][26]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); + expect(lines[2][1]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(lines[2][2]).toEqual({value: '-moz-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); + expect(lines[2][3]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][5]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[2][7]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[2][9]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[2][10]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[2][12]).toEqual({value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(lines[2][14]).toEqual({value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[2][15]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(lines[2][17]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); + expect(lines[3][1]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(lines[3][2]).toEqual({value: '-webkit-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); + expect(lines[3][3]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(lines[3][5]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[3][7]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[3][9]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[3][10]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[3][12]).toEqual({value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(lines[3][14]).toEqual({value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[3][15]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(lines[3][17]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); + expect(lines[4][1]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css']}); + expect(lines[4][2]).toEqual({value: '-o-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); + expect(lines[4][3]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); + expect(lines[4][5]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][7]).toEqual({value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][9]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][10]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[4][12]).toEqual({value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(lines[4][14]).toEqual({value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[4][15]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(lines[5][0]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + expect(lines[5][2]).toEqual({value: '.', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(lines[5][3]).toEqual({value: 'noticebox', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(lines[5][5]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[5][7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + }); + }); + + describe('@namespace', function() { + it('tokenises @namespace statements correctly', function() { + let {tokens} = grammar.tokenizeLine('@namespace "XML";'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css']}); + expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[4]).toEqual({value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine('@namespace prefix "XML" ;')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css']}); + expect(tokens[3]).toEqual({value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); + expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[6]).toEqual({value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[8]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css']}); + expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine('@namespace url("http://a.bc/");')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css']}); + expect(tokens[3]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[6]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + }); + + it("doesn't confuse a prefix of 'url' as a function", function() { + const {tokens} = grammar.tokenizeLine('@namespace url url("http://a.bc/");'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + expect(tokens[3]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); + expect(tokens[5]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(tokens[6]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[8]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); + expect(tokens[9]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + }); + + it('permits injected comments between tokens', function() { + const {tokens} = grammar.tokenizeLine('@namespace/*=*/pre/*=*/"url"/*=*/;'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[5]).toEqual({value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); + expect(tokens[6]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[7]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css']}); + expect(tokens[8]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[9]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[10]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css']}); + expect(tokens[11]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[13]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css']}); + expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + }); + + it('allows no spaces between "@namespace" and quoted URLs', function() { + const {tokens} = grammar.tokenizeLine('@namespace"XML";'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[3]).toEqual({value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css']}); + expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + return expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + }); + + it('tokenises escape sequences in prefixes', function() { + const {tokens} = grammar.tokenizeLine('@namespace pre\\ fix "http://url/";'); + expect(tokens[3]).toEqual({value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); + expect(tokens[4]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css', 'constant.character.escape.css']}); + expect(tokens[5]).toEqual({value: 'fix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); + return expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + }); + + return it('allows arguments to span multiple lines', function() { + let lines = grammar.tokenizeLines(`\ +@namespace +prefix"XML";\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + expect(lines[1][0]).toEqual({value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); + expect(lines[1][1]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[1][2]).toEqual({value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css']}); + expect(lines[1][3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[1][4]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + + lines = grammar.tokenizeLines(`\ +@namespace + + prefix + +url("http://a.bc/");\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + expect(lines[2][1]).toEqual({value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); + expect(lines[4][0]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(lines[4][1]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[4][2]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[4][3]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); + expect(lines[4][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[4][5]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(lines[4][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + }); + }); + + describe('font-feature declarations', function() { + it('tokenises font-feature blocks', function() { + const {tokens} = grammar.tokenizeLine('@font-feature-values Font name 2 { }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.font-features.css']}); + expect(tokens[3]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); + expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('allows font-feature names to start on a different line', function() { + const lines = grammar.tokenizeLines(`\ +@font-feature-values +Font name 2 +{\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css']}); + expect(lines[1][0]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); + return expect(lines[2][0]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('matches injected comments', function() { + const {tokens} = grammar.tokenizeLine('@font-feature-values/*{*/Font/*}*/name/*{*/2{'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[5]).toEqual({value: 'Font', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); + expect(tokens[6]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css']}); + expect(tokens[8]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[9]).toEqual({value: 'name', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); + expect(tokens[10]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[11]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css']}); + expect(tokens[12]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[13]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); + return expect(tokens[14]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('tokenises at-rules for feature names', function() { + const lines = grammar.tokenizeLines(`\ +@swash{ swashy: 2; } +@ornaments{ ident: 2; } +@annotation{ ident: 1; } +@stylistic{ stylish: 2; } +@styleset{ sets: 2 3 4; } +@character-variant{ charvar: 2 }\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css']}); + expect(lines[0][2]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[0][4]).toEqual({value: 'swashy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(lines[0][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); + expect(lines[0][7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[0][8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css']}); + expect(lines[0][10]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[1][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css', 'punctuation.definition.keyword.css']}); + expect(lines[1][1]).toEqual({value: 'ornaments', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css']}); + expect(lines[1][2]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[1][4]).toEqual({value: 'ident', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(lines[1][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); + expect(lines[1][7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[1][8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css']}); + expect(lines[1][10]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[2][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css', 'punctuation.definition.keyword.css']}); + expect(lines[2][1]).toEqual({value: 'annotation', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css']}); + expect(lines[2][2]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[2][4]).toEqual({value: 'ident', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(lines[2][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][7]).toEqual({value: '1', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[2][8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css']}); + expect(lines[2][10]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[3][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css', 'punctuation.definition.keyword.css']}); + expect(lines[3][1]).toEqual({value: 'stylistic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css']}); + expect(lines[3][2]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[3][4]).toEqual({value: 'stylish', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(lines[3][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); + expect(lines[3][7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[3][8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css']}); + expect(lines[3][10]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css', 'punctuation.definition.keyword.css']}); + expect(lines[4][1]).toEqual({value: 'styleset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css']}); + expect(lines[4][2]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[4][4]).toEqual({value: 'sets', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(lines[4][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); + expect(lines[4][7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][9]).toEqual({value: '3', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][11]).toEqual({value: '4', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][12]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css']}); + expect(lines[4][14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[5][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css', 'punctuation.definition.keyword.css']}); + expect(lines[5][1]).toEqual({value: 'character-variant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css']}); + expect(lines[5][2]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[5][4]).toEqual({value: 'charvar', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(lines[5][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); + expect(lines[5][7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + return expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('matches feature-name rules case-insensitively', function() { + const lines = grammar.tokenizeLines(`\ +@sWASH{ swashy: 2; } +@ornaMENts{ ident: 2; } +@anNOTatION{ ident: 1; } +@styLISTic{ stylish: 2; } +@STYLEset{ sets: 2 3 4; } +@CHARacter-VARiant{ charvar: 2 }\ +` + ); + expect(lines[0][1]).toEqual({value: 'sWASH', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css']}); + expect(lines[1][1]).toEqual({value: 'ornaMENts', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css']}); + expect(lines[2][1]).toEqual({value: 'anNOTatION', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css']}); + expect(lines[3][1]).toEqual({value: 'styLISTic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css']}); + expect(lines[4][1]).toEqual({value: 'STYLEset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css']}); + return expect(lines[5][1]).toEqual({value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css']}); + }); + + it('matches comments inside feature-name rules', function() { + const lines = grammar.tokenizeLines(`\ +@font-feature-values Font name 2 { +@swash{/* +========*/swashy:/**/2;/**/} +}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css']}); + expect(lines[0][3]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); + expect(lines[0][5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[1][0]).toEqual({value: '@', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css']}); + expect(lines[1][1]).toEqual({value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css']}); + expect(lines[1][2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[1][3]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][0]).toEqual({value: '========', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css']}); + expect(lines[2][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][2]).toEqual({value: 'swashy', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(lines[2][3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][4]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][5]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][6]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[2][7]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css']}); + expect(lines[2][8]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + return it('highlights escape sequences inside feature-names', function() { + const {tokens} = grammar.tokenizeLine('@swash{ s\\000077a\\73hy: 1; }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css']}); + expect(tokens[4]).toEqual({value: 's', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(tokens[5]).toEqual({value: '\\000077', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[6]).toEqual({value: 'a', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(tokens[7]).toEqual({value: '\\73', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css']}); + return expect(tokens[8]).toEqual({value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + }); + }); + + describe('@page', () => it('tokenises @page blocks correctly', function() { + let {tokens} = grammar.tokenizeLine('@page :first { }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[3]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[4]).toEqual({value: 'first', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[5]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[8]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('@page:right{}')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); + expect(tokens[2]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[3]).toEqual({value: 'right', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('@page{}')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[3]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + })); + + describe('@counter-style', function() { + it('tokenises them and their contents correctly', function() { + const lines = grammar.tokenizeLines(`\ +@counter-style winners-list { + system: fixed; + symbols: url(gold-medal.svg) url(silver-medal.svg) url(bronze-medal.svg); + suffix: " "; +}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); + expect(lines[0][3]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + expect(lines[0][5]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[1][1]).toEqual({value: 'system', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][2]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css']}); + expect(lines[1][4]).toEqual({value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[1][5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); + expect(lines[2][1]).toEqual({value: 'symbols', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[2][2]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][4]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(lines[2][5]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][6]).toEqual({value: 'gold-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css']}); + expect(lines[2][7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][9]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(lines[2][10]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][11]).toEqual({value: 'silver-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css']}); + expect(lines[2][12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][14]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(lines[2][15]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][16]).toEqual({value: 'bronze-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css']}); + expect(lines[2][17]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][18]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); + expect(lines[3][1]).toEqual({value: 'suffix', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[3][2]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css']}); + expect(lines[3][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[3][6]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[3][7]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); + return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('matches injected comments', function() { + const {tokens} = grammar.tokenizeLine('@counter-style/*{*/winners-list/*}*/{ system: fixed; }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[5]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + expect(tokens[6]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css']}); + expect(tokens[8]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[9]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[11]).toEqual({value: 'system', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[12]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css']}); + expect(tokens[14]).toEqual({value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[17]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it("allows the counter-style's name to start on a different line", function() { + const lines = grammar.tokenizeLines(`\ +@counter-style +winners-list\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); + return expect(lines[1][0]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + }); + + return it("highlights escape sequences inside the style's name", function() { + const {tokens} = grammar.tokenizeLine('@counter-style A\\01F602z'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); + expect(tokens[3]).toEqual({value: 'A', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + expect(tokens[4]).toEqual({value: '\\01F602', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css', 'constant.character.escape.codepoint.css']}); + return expect(tokens[5]).toEqual({value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + }); + }); + + describe('@document', () => it('correctly tokenises @document rules', function() { + const lines = grammar.tokenizeLines(`\ +@document url(http://www.w3.org/), +url-prefix(http://www.w3.org/Style/), /* Comment */ +domain(/**/mozilla.org), +regexp("https:.*") { + body{ color: #f00; } +}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: 'document', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css']}); + expect(lines[0][3]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(lines[0][4]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[0][5]).toEqual({value: 'http://www.w3.org/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'variable.parameter.url.css']}); + expect(lines[0][6]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[0][7]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css']}); + expect(lines[1][1]).toEqual({value: 'url-prefix', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css']}); + expect(lines[1][2]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][3]).toEqual({value: 'http://www.w3.org/Style/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'variable.parameter.document-rule.css']}); + expect(lines[1][4]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[1][5]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css']}); + expect(lines[1][7]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[1][8]).toEqual({value: ' Comment ', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css']}); + expect(lines[1][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][1]).toEqual({value: 'domain', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css']}); + expect(lines[2][2]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][3]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][5]).toEqual({value: 'mozilla.org', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'variable.parameter.document-rule.css']}); + expect(lines[2][6]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][7]).toEqual({value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css']}); + expect(lines[3][1]).toEqual({value: 'regexp', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css']}); + expect(lines[3][2]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[3][3]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[3][4]).toEqual({value: 'https:.*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css']}); + expect(lines[3][5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[3][6]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[3][8]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.begin.bracket.curly.css']}); + expect(lines[4][1]).toEqual({value: 'body', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[4][2]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[4][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[4][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[4][7]).toEqual({value: '#', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); + expect(lines[4][8]).toEqual({value: 'f00', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css']}); + expect(lines[4][9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[4][11]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[5][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css']}); + })); + + describe('@viewport', function() { + it('tokenises @viewport blocks correctly', function() { + const {tokens} = grammar.tokenizeLine('@viewport { min-width: 640px; max-width: 800px; }'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'viewport', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css']}); + expect(tokens[2]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[3]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: 'min-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[6]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[8]).toEqual({value: '640', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[12]).toEqual({value: 'max-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[13]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[15]).toEqual({value: '800', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[16]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('tokenises them across lines', function() { + const lines = grammar.tokenizeLines(`\ +@-O-VIEWPORT +{ + zoom: 0.75; + min-zoom: 0.5; + max-zoom: 0.9; +}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: '-O-VIEWPORT', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css']}); + expect(lines[1][0]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[2][1]).toEqual({value: 'zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[2][2]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[2][4]).toEqual({value: '0.75', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[2][5]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[3][1]).toEqual({value: 'min-zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[3][2]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[3][4]).toEqual({value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[3][5]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[4][1]).toEqual({value: 'max-zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[4][2]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[4][4]).toEqual({value: '0.9', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][5]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + return it('tokenises injected comments', function() { + const lines = grammar.tokenizeLines(`\ +@-ms-viewport/*{*/{/* +==*/orientation: landscape; +}\ +` + ); + expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css']}); + expect(lines[0][1]).toEqual({value: '-ms-viewport', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css']}); + expect(lines[0][2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][3]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css']}); + expect(lines[0][4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[0][5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[0][6]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[1][0]).toEqual({value: '==', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css']}); + expect(lines[1][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[1][2]).toEqual({value: 'orientation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[1][5]).toEqual({value: 'landscape', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + }); + + return describe('unknown at-rules', function() { + it('correctly parses single-line unknown at-rules closing with semicolons', function() { + const lines = grammar.tokenizeLines(`\ +@foo; +@foo ; +@foo a; +@foo (); +@foo (a);\ +` + ); + expect(lines[0][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + + expect(lines[1][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + + expect(lines[2][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + expect(lines[2][2]).toEqual({value: ' a', scopes: ['source.css', 'meta.at-rule.header.css']}); + + expect(lines[3][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + expect(lines[3][2]).toEqual({value: ' ()', scopes: ['source.css', 'meta.at-rule.header.css']}); + + expect(lines[4][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + return expect(lines[4][2]).toEqual({value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css']}); + }); + + return it('correctly parses single-line unknown at-rules closing with ;', function() { + const lines = grammar.tokenizeLines(`\ +@foo bar; +.foo\ +` + ); + expect(lines[0][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + + expect(lines[1][0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + return expect(lines[1][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + }); + }); + }); + + describe('capitalisation', function() { + it('ignores case in at-rules', function() { + const lines = grammar.tokenizeLines(`\ +@IMPoRT url("file.css"); +@MEdIA (MAX-WIDTH: 2px){ } +@pAgE :fIRST { } +@NAMEspace "A"; +@foNT-FacE {}\ +` + ); + expect(lines[0][1]).toEqual({value: 'IMPoRT', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(lines[1][1]).toEqual({value: 'MEdIA', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(lines[1][4]).toEqual({value: 'MAX-WIDTH', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(lines[2][1]).toEqual({value: 'pAgE', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); + expect(lines[2][4]).toEqual({value: 'fIRST', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[3][1]).toEqual({value: 'NAMEspace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); + return expect(lines[4][1]).toEqual({value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css']}); + }); + + it('ignores case in property names', function() { + const lines = grammar.tokenizeLines(`\ +a{ COLOR: #fff; } +a{ gRId-tEMPLaTe: none; } +a{ bACkgrOUND-iMAGE: none; } +a{ -MOZ-IMAGE: none; }\ +` + ); + expect(lines[0][3]).toEqual({value: 'COLOR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][3]).toEqual({value: 'gRId-tEMPLaTe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[2][3]).toEqual({value: 'bACkgrOUND-iMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + return expect(lines[3][3]).toEqual({value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); + }); + + it('ignores case in property keywords', function() { + const lines = grammar.tokenizeLines(`\ +a{ color: INItIaL; } +a{ color: trAnsPAREnT; } +a{ color: rED; } +a{ color: unSET; } +a{ color: NONe; } +a{ style: lOWER-lATIN; } +a{ color: -WebkIT-foo; } +a{ font: HelVETica; }\ +` + ); + expect(lines[0][6]).toEqual({value: 'INItIaL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[1][6]).toEqual({value: 'trAnsPAREnT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[2][6]).toEqual({value: 'rED', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(lines[3][6]).toEqual({value: 'unSET', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[4][6]).toEqual({value: 'NONe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(lines[5][6]).toEqual({value: 'lOWER-lATIN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); + expect(lines[6][6]).toEqual({value: '-WebkIT-foo', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); + return expect(lines[7][6]).toEqual({value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + }); + + it('ignores case in selectors', function() { + const lines = grammar.tokenizeLines(`\ +DIV:HOVER { } +#id::BefORE { } +#id::aFTEr { } +TABle:nTH-cHILD(2N+1) {} +htML:NOT(.htiml) {} +I::BACKDROP +I::-mOZ-thing {}\ +` + ); + expect(lines[0][0]).toEqual({value: 'DIV', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[0][2]).toEqual({value: 'HOVER', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[1][3]).toEqual({value: 'BefORE', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(lines[2][3]).toEqual({value: 'aFTEr', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(lines[3][0]).toEqual({value: 'TABle', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[3][2]).toEqual({value: 'nTH-cHILD', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[3][4]).toEqual({value: '2N+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(lines[4][0]).toEqual({value: 'htML', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[4][2]).toEqual({value: 'NOT', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[5][0]).toEqual({value: 'I', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[5][2]).toEqual({value: 'BACKDROP', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + return expect(lines[6][2]).toEqual({value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + }); + + it('ignores case in function names', function() { + const lines = grammar.tokenizeLines(`\ +a{ color: RGBa(); } +a{ color: hslA(); } +a{ color: URL(); } +a{ content: ATTr(); } +a{ content: CoUNTer(); } +a{ content: cuBIC-beZIER()} +a{ content: sTePs()} +a{ content: cALc(2 + 2)}\ +` + ); + expect(lines[0][6]).toEqual({value: 'RGBa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[1][6]).toEqual({value: 'hslA', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[2][6]).toEqual({value: 'URL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(lines[3][6]).toEqual({value: 'ATTr', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[4][6]).toEqual({value: 'CoUNTer', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[5][6]).toEqual({value: 'cuBIC-beZIER', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); + expect(lines[6][6]).toEqual({value: 'sTePs', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); + return expect(lines[7][6]).toEqual({value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); + }); + + return it('ignores case in unit names', function() { + const lines = grammar.tokenizeLines(`\ +a{width: 20EM; } +a{width: 20ReM; } +a{width: 8tURN; } +a{width: 20S; } +a{width: 20CM} +a{width: 2gRAd}\ +` + ); + expect(lines[0][5]).toEqual({value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[0][6]).toEqual({value: 'EM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[1][6]).toEqual({value: 'ReM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.rem.css']}); + expect(lines[2][2]).toEqual({value: 'width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[2][6]).toEqual({value: 'tURN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.turn.css']}); + expect(lines[3][6]).toEqual({value: 'S', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.s.css']}); + expect(lines[4][5]).toEqual({value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][6]).toEqual({value: 'CM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css']}); + return expect(lines[5][6]).toEqual({value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css']}); + }); + }); + + describe('pseudo-classes', function() { + it('tokenizes regular pseudo-classes', function() { + const {tokens} = grammar.tokenizeLine('p:first-child'); + expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + return expect(tokens[2]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + }); + + it("doesn't tokenise pseudo-classes if followed by a semicolon or closed bracket", function() { + const {tokens} = grammar.tokenizeLine('p{ left:left }'); + expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[5]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + describe(':dir()', function() { + it('tokenises :dir() and its keywords', function() { + const lines = grammar.tokenizeLines(`\ +a:dir(ltr ){ } +*:dir( rtl){ }\ +` + ); + expect(lines[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[0][1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[0][2]).toEqual({value: 'dir', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[0][3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[0][4]).toEqual({value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); + expect(lines[0][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); + expect(lines[0][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[1][0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(lines[1][1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[1][2]).toEqual({value: 'dir', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[1][3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][4]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); + expect(lines[1][5]).toEqual({value: 'rtl', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); + return expect(lines[1][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + return it('allows :dir() to include comments and newlines', function() { + const lines = grammar.tokenizeLines(`\ +:DIR(/** +==*/ltr/* +*/)\ +` + ); + expect(lines[0][0]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(lines[0][1]).toEqual({value: 'DIR', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(lines[0][2]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[0][3]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[0][4]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css']}); + expect(lines[1][0]).toEqual({value: '==', scopes: ['source.css', 'meta.selector.css', 'comment.block.css']}); + expect(lines[1][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[1][2]).toEqual({value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); + expect(lines[1][3]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(lines[2][1]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + }); + + describe(':lang()', function() { + it('tokenizes :lang()', function() { + const {tokens} = grammar.tokenizeLine(':lang(zh-Hans-CN,es-419)'); + expect(tokens[0]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[2]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[3]).toEqual({value: 'zh-Hans-CN', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css']}); + expect(tokens[4]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[5]).toEqual({value: 'es-419', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css']}); + return expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + it('does not tokenize unquoted language ranges containing asterisks', function() { + const {tokens} = grammar.tokenizeLine(':lang(zh-*-CN)'); + return expect(tokens[3]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css']}); + }); + + return it('tokenizes language ranges containing asterisks quoted as strings', function() { + const {tokens} = grammar.tokenizeLine(':lang("zh-*-CN",\'*-ab-\')'); + expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[4]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'support.constant.language-range.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[6]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[7]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[8]).toEqual({value: '*-ab-', scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'support.constant.language-range.css']}); + return expect(tokens[9]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + }); + }); + + describe(':not()', function() { + it('tokenises other selectors inside :not()', function() { + const {tokens} = grammar.tokenizeLine('*:not(.class-name):not(div) {}'); + expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[2]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[5]).toEqual({value: 'class-name', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[7]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[8]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[10]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + return expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + return it('tokenises injected comments', function() { + const {tokens} = grammar.tokenizeLine('*:not(/*(*/.class-name/*)*/):not(/*b*/) {}'); + expect(tokens[2]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'comment.block.css']}); + expect(tokens[6]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[7]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[8]).toEqual({value: 'class-name', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[9]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'comment.block.css']}); + expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[13]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[14]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[15]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[16]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[17]).toEqual({value: 'b', scopes: ['source.css', 'meta.selector.css', 'comment.block.css']}); + expect(tokens[18]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + }); + + return describe(':nth-*()', function() { + it('tokenizes :nth-child()', function() { + const tokens = grammar.tokenizeLines(`\ +:nth-child(2n+1) +:nth-child(2n -1) +:nth-child(-2n+ 1) +:nth-child(-2n - 1) +:nth-child(odd) +:nth-child(even) +:nth-child( odd ) +:nth-child( even )\ +` + ); + expect(tokens[0][0]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[0][1]).toEqual({value: 'nth-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[0][2]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[0][3]).toEqual({value: '2n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[0][4]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[1][3]).toEqual({value: '2n -1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[2][3]).toEqual({value: '-2n+ 1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[3][3]).toEqual({value: '-2n - 1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[4][3]).toEqual({value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); + expect(tokens[5][3]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); + expect(tokens[6][3]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[6][4]).toEqual({value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); + expect(tokens[7][4]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); + return expect(tokens[7][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); + }); + + it('tokenizes :nth-last-child()', function() { + const tokens = grammar.tokenizeLines(`\ +:nth-last-child(2n) +:nth-last-child( -2n) +:nth-last-child( 2n ) +:nth-last-child(even)\ +` + ); + expect(tokens[0][0]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[0][1]).toEqual({value: 'nth-last-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[0][2]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[0][3]).toEqual({value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[0][4]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[1][4]).toEqual({value: '-2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[2][4]).toEqual({value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[2][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[3][3]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); + }); + + it('tokenizes :nth-of-type()', function() { + const tokens = grammar.tokenizeLines(`\ +img:nth-of-type(+n+1) +img:nth-of-type(-n+1) +img:nth-of-type(n+1)\ +` + ); + expect(tokens[0][1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[0][2]).toEqual({value: 'nth-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[0][3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[0][4]).toEqual({value: '+n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[0][5]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[1][4]).toEqual({value: '-n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + return expect(tokens[2][4]).toEqual({value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + }); + + return it('tokenizes ::nth-last-of-type()', function() { + const tokens = grammar.tokenizeLines(`\ +h1:nth-last-of-type(-1) +h1:nth-last-of-type(+2) +h1:nth-last-of-type(3)\ +` + ); + expect(tokens[0][1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + expect(tokens[0][2]).toEqual({value: 'nth-last-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[0][3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[0][4]).toEqual({value: '-1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[0][5]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[1][4]).toEqual({value: '+2', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + return expect(tokens[2][4]).toEqual({value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + }); + }); + }); + + describe('pseudo-elements', function() { + // :first-line, :first-letter, :before and :after + it('tokenizes both : and :: notations for pseudo-elements introduced in CSS 1 and 2', function() { + let {tokens} = grammar.tokenizeLine('.opening:first-letter'); + expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'opening', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[2]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + expect(tokens[3]).toEqual({value: 'first-letter', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + + ({tokens} = grammar.tokenizeLine('q::after')); + expect(tokens[0]).toEqual({value: 'q', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + return expect(tokens[2]).toEqual({value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + }); + + it('tokenizes both : and :: notations for vendor-prefixed pseudo-elements', function() { + let {tokens} = grammar.tokenizeLine(':-ms-input-placeholder'); + expect(tokens[0]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: '-ms-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + + ({tokens} = grammar.tokenizeLine('::-webkit-input-placeholder')); + expect(tokens[0]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + return expect(tokens[1]).toEqual({value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + }); + + return it('only tokenizes the :: notation for other pseudo-elements', function() { + let {tokens} = grammar.tokenizeLine('::selection'); + expect(tokens[0]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + expect(tokens[1]).toEqual({value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + + ({tokens} = grammar.tokenizeLine(':selection')); + return expect(tokens[0]).toEqual({value: ':selection', scopes: ['source.css', 'meta.selector.css']}); + }); + }); + + return describe('compound selectors', function() { + it('tokenizes the combination of type selectors followed by class selectors', function() { + const {tokens} = grammar.tokenizeLine('very-custom.class'); + expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); + return expect(tokens[2]).toEqual({value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + }); + + it('tokenizes the combination of type selectors followed by pseudo-classes', function() { + const {tokens} = grammar.tokenizeLine('very-custom:hover'); + expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); + return expect(tokens[2]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + }); + + return it('tokenizes the combination of type selectors followed by pseudo-elements', function() { + const {tokens} = grammar.tokenizeLine('very-custom::shadow'); + expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[1]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); + return expect(tokens[2]).toEqual({value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + }); + }); +}); + + describe('property lists (declaration blocks)', function() { + it('tokenizes inline property lists', function() { + const {tokens} = grammar.tokenizeLine('div { font-size: inherit; }'); + expect(tokens[4]).toEqual({value: 'font-size', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[7]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('tokenizes compact inline property lists', function() { + const {tokens} = grammar.tokenizeLine('div{color:inherit;float:left}'); + expect(tokens[2]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[4]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[6]).toEqual({value: 'float', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[7]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[8]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + return expect(tokens[9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('tokenizes multiple inline property lists', function() { + const tokens = grammar.tokenizeLines(`\ +very-custom { color: inherit } +another-one { display : none ; }\ +` + ); + expect(tokens[0][0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[0][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[0][5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[0][7]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[0][8]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[1][0]).toEqual({value: 'another-one', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[1][4]).toEqual({value: 'display', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[1][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[1][6]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[1][8]).toEqual({value: 'none', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[1][9]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[1][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[1][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('tokenizes custom properties', function() { + const {tokens} = grammar.tokenizeLine(':root { --white: #FFF; }'); + return expect(tokens[5]).toEqual({value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css']}); + }); + + it('tokenises commas between property values', function() { + const {tokens} = grammar.tokenizeLine('a{ text-shadow: a, b; }'); + return expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + }); + + it('tokenises superfluous semicolons', function() { + const lines = grammar.tokenizeLines(`\ +.test{ width: 20em;;;;;;;;; +;;;;;;;;;height: 10em; }\ +` + ); + for (let i = 0; i <= 8; i++) { + expect(lines[0][i+9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[1][i]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + } + return expect(lines[1][9]).toEqual({value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + }); + + return describe('values', function() { + it('tokenizes color keywords', function() { + const {tokens} = grammar.tokenizeLine('#jon { color: snow; }'); + return expect(tokens[8]).toEqual({value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css']}); + }); + + it('tokenises RGBA values in hex notation', function() { + let {tokens} = grammar.tokenizeLine('p{ color: #f030; }'); + expect(tokens[6]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); + expect(tokens[7]).toEqual({value: 'f030', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('a{ color: #CAFEBABE; }')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); + expect(tokens[7]).toEqual({value: 'CAFEBABE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('a{ color: #CAFEBABEF; }')); + return expect(tokens[6]).toEqual({value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + }); + + it('tokenizes common font names', function() { + const {tokens} = grammar.tokenizeLine('p { font-family: Verdana, Helvetica, sans-serif; }'); + expect(tokens[7]).toEqual({value: 'Verdana', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + expect(tokens[10]).toEqual({value: 'Helvetica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + return expect(tokens[13]).toEqual({value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + }); + + it('tokenizes predefined list style types', function() { + const {tokens} = grammar.tokenizeLine('ol.myth { list-style-type: cjk-earthly-branch }'); + return expect(tokens[9]).toEqual({value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); + }); + + it('tokenizes numeric values', function() { + const {tokens} = grammar.tokenizeLine('div { font-size: 14px; }'); + expect(tokens[7]).toEqual({value: '14', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + return expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + }); + + it('does not tokenize invalid numeric values', function() { + let {tokens} = grammar.tokenizeLine('div { font-size: test14px; }'); + expect(tokens[7]).toEqual({value: 'test14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + + ({tokens} = grammar.tokenizeLine('div { font-size: test-14px; }')); + return expect(tokens[7]).toEqual({value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + }); + + it('tokenizes vendor-prefixed values', function() { + let {tokens} = grammar.tokenizeLine('.edge { cursor: -webkit-zoom-in; }'); + expect(tokens[8]).toEqual({value: '-webkit-zoom-in', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); + + ({tokens} = grammar.tokenizeLine('.edge { width: -moz-min-content; }')); + expect(tokens[8]).toEqual({value: '-moz-min-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); + + ({tokens} = grammar.tokenizeLine('.edge { display: -ms-grid; }')); + return expect(tokens[8]).toEqual({value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); + }); + + it('tokenizes custom variables', function() { + const {tokens} = grammar.tokenizeLine('div { color: var(--primary-color) }'); + return expect(tokens[9]).toEqual({value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); + }); + + it('tokenises numeric values correctly', function() { + const lines = grammar.tokenizeLines(`\ +.a { a: 12em } +.a { a: 4.01ex } +.a { a: -456.8ch } +.a { a: 0.0REM } +.a { a: +0.0vh } +.a { a: -0.0vw } +.a { a: .6px } +.a { a: 10e3mm } +.a { a: 10E3cm } +.a { a: -3.4e+2In } +.a { a: -3.4e-2ch } +.a { a: +.5E-2% } +.a { a: -3.4e-2% }\ +` + ); + expect(lines[0][8]).toEqual({value: '12', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[0][9]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[1][8]).toEqual({value: '4.01', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[1][9]).toEqual({value: 'ex', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ex.css']}); + expect(lines[2][8]).toEqual({value: '-456.8', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[2][9]).toEqual({value: 'ch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ch.css']}); + expect(lines[3][8]).toEqual({value: '0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[3][9]).toEqual({value: 'REM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.rem.css']}); + expect(lines[4][8]).toEqual({value: '+0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[4][9]).toEqual({value: 'vh', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.vh.css']}); + expect(lines[5][8]).toEqual({value: '-0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[5][9]).toEqual({value: 'vw', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.vw.css']}); + expect(lines[6][8]).toEqual({value: '.6', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[6][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[7][8]).toEqual({value: '10e3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[7][9]).toEqual({value: 'mm', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.mm.css']}); + expect(lines[8][8]).toEqual({value: '10E3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[8][9]).toEqual({value: 'cm', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css']}); + expect(lines[9][8]).toEqual({value: '-3.4e+2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[9][9]).toEqual({value: 'In', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.in.css']}); + expect(lines[10][8]).toEqual({value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[10][9]).toEqual({value: 'ch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ch.css']}); + expect(lines[11][8]).toEqual({value: '+.5E-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(lines[11][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(lines[12][8]).toEqual({value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + return expect(lines[12][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + }); + + describe('functional notation', function() { + describe('attr()', function() { + it('tokenises parameters correctly and case-insensitively', function() { + const {tokens} = grammar.tokenizeLine('a{content:aTTr(data-width px, inherit)}'); + expect(tokens[4]).toEqual({value: 'aTTr', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[6]).toEqual({value: 'data-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[11]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.constant.property-value.css']}); + expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + return it('matches variables', function() { + const {tokens} = grammar.tokenizeLine('a{content:ATTR(VAR(--name) px, "N/A")}'); + expect(tokens[4]).toEqual({value: 'ATTR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[6]).toEqual({value: 'VAR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[11]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(tokens[12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[14]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[15]).toEqual({value: 'N/A', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css']}); + expect(tokens[16]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + return expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + }); + + describe('calc()', function() { + it('tokenises calculations', function() { + const lines = grammar.tokenizeLines(`\ +a{ + width: calc(3px + -1em); + width: calc(3px - -1em); + width: calc(3px * 2); + width: calc(3px / 2); +}\ +` + ); + expect(lines[1][4]).toEqual({value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); + expect(lines[1][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][6]).toEqual({value: '3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(lines[1][7]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[1][9]).toEqual({value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); + expect(lines[1][11]).toEqual({value: '-1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(lines[1][12]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[1][13]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][9]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); + expect(lines[2][11]).toEqual({value: '-1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(lines[2][12]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[3][7]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[3][9]).toEqual({value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); + expect(lines[4][7]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[4][9]).toEqual({value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); + return expect(lines[4][11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + }); + + it('requires whitespace around + and - operators', function() { + let {tokens} = grammar.tokenizeLine('a{ width: calc(3px+1em); }'); + expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[10]).toEqual({value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); + expect(tokens[11]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(tokens[12]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + + ({tokens} = grammar.tokenizeLine('a{ width: calc(3px--1em); height: calc(10-1em);}')); + expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[10]).toEqual({value: '--1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); + expect(tokens[19]).toEqual({value: '10', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + return expect(tokens[20]).toEqual({value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); + }); + + it('does not require whitespace around * and / operators', function() { + let {tokens} = grammar.tokenizeLine('a{ width: calc(3px*2); }'); + expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[10]).toEqual({value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); + expect(tokens[11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + + ({tokens} = grammar.tokenizeLine('a{ width: calc(3px/2); }')); + expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[10]).toEqual({value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); + return expect(tokens[11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + }); + + return it('matches variable expansions inside calculations', function() { + const {tokens} = grammar.tokenizeLine('.foo { margin-top: calc(var(--gap) + 1px); }'); + expect(tokens[8]).toEqual({value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); + expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[10]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(tokens[11]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[12]).toEqual({value: '--gap', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(tokens[13]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[15]).toEqual({value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); + expect(tokens[17]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(tokens[18]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[20]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + }); + + describe('colours', function() { + it('tokenises colour functions correctly', function() { + let {tokens} = grammar.tokenizeLine('a{ color: rgb(187,255,221); }'); + expect(tokens[6]).toEqual({value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '187', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[10]).toEqual({value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[11]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[12]).toEqual({value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[13]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + + ({tokens} = grammar.tokenizeLine('a{ color: RGBa( 100%, 0% ,20.17% ,.5 ); }')); + expect(tokens[6]).toEqual({value: 'RGBa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[9]).toEqual({value: '100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[10]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(tokens[11]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[13]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[14]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(tokens[16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[17]).toEqual({value: '20.17', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[18]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(tokens[20]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[21]).toEqual({value: '.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[23]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + + ({tokens} = grammar.tokenizeLine('a{color:HSL(0, 00100%,50%)}')); + expect(tokens[4]).toEqual({value: 'HSL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[6]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[9]).toEqual({value: '00100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[10]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(tokens[11]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[12]).toEqual({value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[13]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(tokens[14]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + + ({tokens} = grammar.tokenizeLine('a{color:HSLa(2,.0%,1%,.7)}')); + expect(tokens[4]).toEqual({value: 'HSLa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[6]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[8]).toEqual({value: '.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(tokens[10]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[11]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[12]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(tokens[13]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[14]).toEqual({value: '.7', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + return expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + it('matches variables as colour components', function() { + const {tokens} = grammar.tokenizeLine('a{ color: RGBA(var(--red), 0% , 20%, .2)}'); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[10]).toEqual({value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + }); + + it('matches comments between colour components', function() { + const {tokens} = grammar.tokenizeLine('a{ color: rgba(/**/255/*=*/,0,/*2.2%*/51/*,*/0.2)}'); + expect(tokens[8]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[10]).toEqual({value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[11]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[12]).toEqual({value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); + expect(tokens[13]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[14]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[17]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[19]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[20]).toEqual({value: '51', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[21]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[22]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); + expect(tokens[23]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(tokens[24]).toEqual({value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + }); + + return it('allows colour components to be split across lines', function() { + const lines = grammar.tokenizeLines(`\ +.frost{ + background-color: rgba( + var(--red), /* Red */ + var(--green), /* Green */ + var(--blue), /* Blue */ + /* var(--test), + /**/var(--opacity) /* Transparency */ + ); +}\ +` + ); + expect(lines[1][4]).toEqual({value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[1][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][1]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(lines[2][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][3]).toEqual({value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(lines[2][4]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][8]).toEqual({value: ' Red ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); + expect(lines[3][1]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(lines[3][3]).toEqual({value: '--green', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(lines[3][5]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(lines[3][8]).toEqual({value: ' Green ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); + expect(lines[4][1]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(lines[4][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[4][3]).toEqual({value: '--blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(lines[4][4]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[4][5]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(lines[4][8]).toEqual({value: ' Blue ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); + expect(lines[4][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[5][1]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[5][2]).toEqual({value: ' var(--test),', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); + expect(lines[6][0]).toEqual({value: ' /*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); + expect(lines[6][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[6][2]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(lines[6][3]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[6][4]).toEqual({value: '--opacity', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(lines[6][5]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[6][7]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[6][8]).toEqual({value: ' Transparency ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); + expect(lines[6][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(lines[7][1]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + }); + + describe('gradients', function() { + it('tokenises linear gradients', function() { + let {tokens} = grammar.tokenizeLine('a{ background-image: linear-gradient( 45deg, blue, red ); }'); + expect(tokens[6]).toEqual({value: 'linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[9]).toEqual({value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css']}); + expect(tokens[10]).toEqual({value: 'deg', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.deg.css']}); + expect(tokens[11]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[13]).toEqual({value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(tokens[14]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[16]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(tokens[18]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[19]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine('a{ background-image: LINear-graDIEnt( ellipse to left top, blue, red);')); + expect(tokens[6]).toEqual({value: 'LINear-graDIEnt', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css']}); + expect(tokens[9]).toEqual({value: 'ellipse', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(tokens[11]).toEqual({value: 'to', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css']}); + expect(tokens[13]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(tokens[15]).toEqual({value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(tokens[16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[18]).toEqual({value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(tokens[19]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); + return expect(tokens[21]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); + }); + + it('tokenises radial gradients', function() { + let {tokens} = grammar.tokenizeLine('a{ background-image: radial-gradient(farthest-corner at 45px 45px , #f00 0%, #00f 100%);}'); + expect(tokens[6]).toEqual({value: 'radial-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: 'farthest-corner', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(tokens[10]).toEqual({value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css']}); + expect(tokens[12]).toEqual({value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css']}); + expect(tokens[13]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[15]).toEqual({value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css']}); + expect(tokens[16]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[18]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[20]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); + expect(tokens[21]).toEqual({value: 'f00', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); + expect(tokens[23]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css']}); + expect(tokens[24]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + + ({tokens} = grammar.tokenizeLine('a{ background-image: RADial-gradiENT(16px at 60px 50%,#000 0%, #000 14px, rgba(0,0,0,.3) 18px, transparent 19px)}')); + expect(tokens[6]).toEqual({value: 'RADial-gradiENT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '16', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css']}); + expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[11]).toEqual({value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css']}); + expect(tokens[13]).toEqual({value: '60', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css']}); + expect(tokens[14]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[16]).toEqual({value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css']}); + expect(tokens[17]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(tokens[18]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[19]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); + expect(tokens[20]).toEqual({value: '000', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); + expect(tokens[33]).toEqual({value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(tokens[34]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[35]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[36]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[41]).toEqual({value: '.3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[42]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[48]).toEqual({value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + }); + + it('matches gradients that span multiple lines with injected comments', function() { + const lines = grammar.tokenizeLines(`\ +a{ + background-image: raDIAL-gradiENT( + ellipse farthest-corner/*@*/at/*@*/470px 47px,/*=== +========*/#FFFF80 20%, rgba(204, 153, 153, 0.4) 30%,/*))))))))}*/#E6E6FF 60%); }\ +` + ); + expect(lines[1][4]).toEqual({value: 'raDIAL-gradiENT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css']}); + expect(lines[2][1]).toEqual({value: 'ellipse', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(lines[2][3]).toEqual({value: 'farthest-corner', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(lines[2][4]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][5]).toEqual({value: '@', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); + expect(lines[2][6]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[2][7]).toEqual({value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css']}); + expect(lines[2][8]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][11]).toEqual({value: '470', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css']}); + expect(lines[2][12]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(lines[2][16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[2][17]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[2][18]).toEqual({value: '===', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); + expect(lines[3][0]).toEqual({value: '========', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); + expect(lines[3][2]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); + expect(lines[3][3]).toEqual({value: 'FFFF80', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); + expect(lines[3][9]).toEqual({value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[3][10]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[3][20]).toEqual({value: '0.4', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[3][21]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[3][26]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[3][27]).toEqual({value: '))))))))}', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); + expect(lines[3][28]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[3][29]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); + return expect(lines[3][30]).toEqual({value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); + }); + + it('highlights vendored gradient functions', function() { + const lines = grammar.tokenizeLines(`\ +.grad { + background-image: -webkit-linear-gradient(top, /* For Chrome 25 and Safari 6, iOS 6.1, Android 4.3 */ hsl(0, 80%, 70%), #bada55); + background-image: -moz-linear-gradient(top, /* For Firefox (3.6 to 15) */ hsl(0, 80%, 70%), #bada55); + background-image: -o-linear-gradient(top, /* For old Opera (11.1 to 12.0) */ hsl(0, 80%, 70%), #bada55); +}\ +` + ); + expect(lines[1][4]).toEqual({value: '-webkit-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css']}); + expect(lines[1][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][6]).toEqual({value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(lines[1][10]).toEqual({value: ' For Chrome 25 and Safari 6, iOS 6.1, Android 4.3 ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); + expect(lines[1][13]).toEqual({value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[1][22]).toEqual({value: '70', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[1][23]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(lines[1][24]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[1][27]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); + expect(lines[1][28]).toEqual({value: 'bada55', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); + expect(lines[1][29]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][4]).toEqual({value: '-moz-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css']}); + expect(lines[2][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][6]).toEqual({value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(lines[2][7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[2][10]).toEqual({value: ' For Firefox (3.6 to 15) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); + expect(lines[2][13]).toEqual({value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[2][14]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][24]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][29]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[3][4]).toEqual({value: '-o-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css']}); + expect(lines[3][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[3][10]).toEqual({value: ' For old Opera (11.1 to 12.0) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); + expect(lines[3][13]).toEqual({value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); + return expect(lines[3][14]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + }); + + return it('highlights antique Webkit syntax as deprecated', function() { + const lines = grammar.tokenizeLines(`\ +.grad { + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, + from( rgb(0, 171, 235)), + color-stop(0.5, rgb(255, 255, 255)), + color-stop(0.5, rgb(102, 204, 0)), + to(rgb(255, 255, 255))), + -webkit-gradient(radial, 45 45, 10, 52 50, 30, from(#A7D30C), to(rgba(1,159,98,0)), color-stop(90%, #019F62)), + -webkit-gradient(radial, 105 105, 20, 112 120, 50, from(#ff5f98), to(rgba(255,1,136,0)), color-stop(75%, #ff0188)), + -webkit-gradient(radial, 95 15, 15, 102 20, 40, from(#00c9ff), to(rgba(0,201,255,0)), color-stop(80%, #00b5e2)), + -webkit-gradient(radial, 0 150, 50, 0 140, 90, from(#f4f201), to(rgba(228, 199,0,0)), color-stop(80%, #e4c700)); +}\ +` + ); + expect(lines[1][4]).toEqual({value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css']}); + expect(lines[1][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][6]).toEqual({value: 'linear', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css']}); + expect(lines[1][7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[1][19]).toEqual({value: '100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); + expect(lines[1][20]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(lines[2][1]).toEqual({value: 'from', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css']}); + expect(lines[2][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][4]).toEqual({value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[2][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][9]).toEqual({value: '171', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[2][10]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(lines[2][14]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[3][1]).toEqual({value: 'color-stop', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css']}); + expect(lines[3][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[3][3]).toEqual({value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); + expect(lines[3][4]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[3][16]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[3][17]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[4][1]).toEqual({value: 'color-stop', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css']}); + expect(lines[4][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[4][3]).toEqual({value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); + expect(lines[4][4]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[4][6]).toEqual({value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[4][7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[4][8]).toEqual({value: '102', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[4][9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(lines[4][11]).toEqual({value: '204', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[4][12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(lines[4][14]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(lines[4][15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[4][16]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[4][17]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[5][1]).toEqual({value: 'to', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css']}); + expect(lines[5][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[5][12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[5][13]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[5][14]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[5][15]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + expect(lines[6][1]).toEqual({value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css']}); + expect(lines[6][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[6][3]).toEqual({value: 'radial', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css']}); + expect(lines[6][4]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[6][8]).toEqual({value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); + expect(lines[6][31]).toEqual({value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); + expect(lines[7][1]).toEqual({value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css']}); + expect(lines[7][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[9][1]).toEqual({value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css']}); + expect(lines[9][2]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[9][3]).toEqual({value: 'radial', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css']}); + expect(lines[9][4]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css']}); + expect(lines[9][6]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); + expect(lines[9][8]).toEqual({value: '150', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); + expect(lines[9][54]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[9][55]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(lines[10][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + }); + + describe('other functions', function() { + it('tokenises basic-shape functions', function() { + const lines = grammar.tokenizeLines(`\ +a{ + shape-outside: circle(20em/*=*/at 50% 50%); + shape-outside: inset(1em, 1em, 1em, 1em); +}\ +` + ); + expect(lines[1][4]).toEqual({value: 'circle', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'support.function.shape.css']}); + expect(lines[1][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][6]).toEqual({value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); + expect(lines[1][7]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[1][8]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[1][9]).toEqual({value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css']}); + expect(lines[1][10]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(lines[1][11]).toEqual({value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'keyword.operator.shape.css']}); + expect(lines[1][13]).toEqual({value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); + expect(lines[1][14]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(lines[1][16]).toEqual({value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); + expect(lines[1][17]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(lines[1][18]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][4]).toEqual({value: 'inset', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'support.function.shape.css']}); + expect(lines[2][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][6]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); + expect(lines[2][7]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[2][8]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css']}); + expect(lines[2][10]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); + expect(lines[2][11]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[2][12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css']}); + expect(lines[2][14]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); + expect(lines[2][15]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(lines[2][16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css']}); + expect(lines[2][18]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); + expect(lines[2][19]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + return expect(lines[2][20]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + it('tokenises OpenType feature functions', function() { + const lines = grammar.tokenizeLines(`\ +.font{ + font-variant-alternates: stylistic(user-defined-ident); + font-variant-alternates: styleset(user-defined-ident); + font-variant-alternates: character-variant(user-defined-ident); + font-variant-alternates: swash(user-defined-ident); + font-variant-alternates: ornaments(user-defined-ident); + font-variant-alternates: annotation(user-defined-ident); + font-variant-alternates: swash(ident1) annotation(ident2); +}\ +` + ); + expect(lines[1][4]).toEqual({value: 'stylistic', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[1][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][6]).toEqual({value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(lines[1][7]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][4]).toEqual({value: 'styleset', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[2][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[2][6]).toEqual({value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(lines[2][7]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[3][4]).toEqual({value: 'character-variant', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[3][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[3][6]).toEqual({value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(lines[3][7]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[4][4]).toEqual({value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[4][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[4][6]).toEqual({value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(lines[4][7]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[5][4]).toEqual({value: 'ornaments', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[5][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[5][6]).toEqual({value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(lines[5][7]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[6][4]).toEqual({value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[6][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[6][6]).toEqual({value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(lines[6][7]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[7][4]).toEqual({value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[7][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[7][6]).toEqual({value: 'ident1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + expect(lines[7][7]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[7][9]).toEqual({value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[7][10]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[7][11]).toEqual({value: 'ident2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); + return expect(lines[7][12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + return it('tokenises image-set()', function() { + const lines = grammar.tokenizeLines(`\ +a{ + background-image: image-set( "foo.png" 1x, + "foo-2x.png" 2x, + "foo-print.png" 600dpi ); +}\ +` + ); + expect(lines[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(lines[0][1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[1][1]).toEqual({value: 'background-image', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][2]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[1][4]).toEqual({value: 'image-set', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); + expect(lines[1][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[1][7]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[1][8]).toEqual({value: 'foo.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css']}); + expect(lines[1][9]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[1][11]).toEqual({value: '1x', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.other.density.css']}); + expect(lines[1][12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css']}); + expect(lines[2][1]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[2][2]).toEqual({value: 'foo-2x.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css']}); + expect(lines[2][3]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[2][5]).toEqual({value: '2x', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.other.density.css']}); + expect(lines[2][6]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css']}); + expect(lines[3][1]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[3][2]).toEqual({value: 'foo-print.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css']}); + expect(lines[3][3]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[3][5]).toEqual({value: '600', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css']}); + expect(lines[3][6]).toEqual({value: 'dpi', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css', 'keyword.other.unit.dpi.css']}); + expect(lines[3][8]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[3][9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + }); + + describe('timing-functions', function() { + it('tokenises them correctly', function() { + const {tokens} = grammar.tokenizeLine('a{ zoom: cubic-bezier(/**/1.2,/*=*/0,0,0/**/)}'); + expect(tokens[6]).toEqual({value: 'cubic-bezier', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[10]).toEqual({value: '1.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css']}); + expect(tokens[11]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[13]).toEqual({value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css']}); + expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[15]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css']}); + expect(tokens[16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[17]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css']}); + expect(tokens[18]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[19]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css']}); + expect(tokens[20]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[21]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(tokens[22]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + return it('highlights the "start" and "end" keywords', function() { + const {tokens} = grammar.tokenizeLine('a{ before: steps(0, start); after: steps(1, end); }'); + expect(tokens[6]).toEqual({value: 'steps', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css']}); + expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[11]).toEqual({value: 'start', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); + expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[23]).toEqual({value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); + }); + }); + + describe('variables', function() { + it('scopes var() statements as variables', function() { + let {tokens} = grammar.tokenizeLine('a{color: var(--name)}'); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[5]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(tokens[6]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[7]).toEqual({value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('a{color: var( --name )}')); + expect(tokens[5]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(tokens[6]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); + return expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + it('allows injected comments', function() { + const {tokens} = grammar.tokenizeLine('a{ color: var( /*=*/ --something ) }'); + expect(tokens[6]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[9]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[10]).toEqual({value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css']}); + expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[13]).toEqual({value: '--something', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); + return expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + }); + + return it('tokenises fallback values', function() { + const {tokens} = grammar.tokenizeLine('.bar{ width: var(--page-width, /*;;;);*/ 2); }'); + expect(tokens[7]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); + expect(tokens[8]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[9]).toEqual({value: '--page-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(tokens[10]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[13]).toEqual({value: ';;;);', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css']}); + expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[16]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'constant.numeric.css']}); + expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[18]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + }); + }); + + return it('does not tokenise functions with whitespace between name and parameters', function() { + let {tokens} = grammar.tokenizeLine('a{ p: attr (title); }'); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: 'p', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css']}); + expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: 'attr (title', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('a{url:url (s)}')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: 'url', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css']}); + expect(tokens[3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[4]).toEqual({value: 'url (s', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[5]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('a{content:url ("http://github.com/");}')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[4]).toEqual({value: 'url (', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[6]).toEqual({value: 'http://github.com/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('a{content: url (http://a.pl/)}')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[5]).toEqual({value: 'url (http://a.pl/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + + ({tokens} = grammar.tokenizeLine('a{ color: rgb (187,255,221); }')); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: 'rgb (', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[7]).toEqual({value: '187', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[8]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[9]).toEqual({value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[10]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[11]).toEqual({value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[13]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[15]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + }); + + return describe('Unicode ranges', function() { + it('tokenises single codepoints', function() { + const {tokens} = grammar.tokenizeLine('a{ a: U+A5 }'); + return expect(tokens[6]).toEqual({value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + }); + + it('tokenises codepoint ranges', function() { + let {tokens} = grammar.tokenizeLine('a{ a: U+0025-00FF }'); + expect(tokens[6]).toEqual({value: 'U+0025', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); + expect(tokens[8]).toEqual({value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + + ({tokens} = grammar.tokenizeLine('a{ unicode-range: u+0-7F }')); + expect(tokens[6]).toEqual({value: 'u+0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); + return expect(tokens[8]).toEqual({value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + }); + + return it('tokenises wildcard ranges', function() { + let {tokens} = grammar.tokenizeLine('a{ unicode-range: U+4?? }'); + expect(tokens[6]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + + ({tokens} = grammar.tokenizeLine('a{ unicode-range: U+0025-00FF, U+4?? }')); + expect(tokens[6]).toEqual({value: 'U+0025', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); + expect(tokens[8]).toEqual({value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + return expect(tokens[11]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + }); + }); + }); +}); + + describe('escape sequences', function() { + it('tokenizes escape sequences in single-quoted strings', function() { + const {tokens} = grammar.tokenizeLine("very-custom { content: '\\c0ffee' }"); + + expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[1]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[4]).toEqual({value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[7]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + return expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css']}); + }); + + it('tokenizes escape sequences in double-quoted strings', function() { + const {tokens} = grammar.tokenizeLine('very-custom { content: "\\c0ffee" }'); + + expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[1]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[4]).toEqual({value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + return expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css']}); + }); + + it('tokenises escape sequences in selectors', function() { + let {tokens} = grammar.tokenizeLine('\\61 \\{ { } \\}'); + expect(tokens[0]).toEqual({value: '\\61', scopes: ['source.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'constant.character.escape.css']}); + expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[8]).toEqual({value: '\\}', scopes: ['source.css', 'constant.character.escape.css']}); + + ({tokens} = grammar.tokenizeLine('\\61\\ \\. \\@media {}')); // Matches <.><@media> + expect(tokens[0]).toEqual({value: '\\61', scopes: ['source.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[1]).toEqual({value: '\\ ', scopes: ['source.css', 'constant.character.escape.css']}); + expect(tokens[2]).toEqual({value: '\\.', scopes: ['source.css', 'constant.character.escape.css']}); + expect(tokens[4]).toEqual({value: '\\@', scopes: ['source.css', 'constant.character.escape.css']}); + expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css']}); + return expect(tokens[7]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + }); + + it('tokenises escape sequences in property lists', function() { + const {tokens} = grammar.tokenizeLine('a { \\77\\69\\64\\74\\68: 20px; }'); // Same as writing "width: 20px" + expect(tokens[4]).toEqual({value: '\\77', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[5]).toEqual({value: '\\69', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[6]).toEqual({value: '\\64', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[7]).toEqual({value: '\\74', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[8]).toEqual({value: '\\68', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); + return expect(tokens[9]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + }); + + return it('tokenises escape sequences in property values', function() { + const {tokens} = grammar.tokenizeLine('a { content: \\1F764; }'); + expect(tokens[7]).toEqual({value: '\\1F764', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); +}); + + describe('unclosed strings', function() { + it('highlights an unterminated string as an error', function() { + let {tokens} = grammar.tokenizeLine("a{ content: 'aaaa"); + expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[7]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); + + ({tokens} = grammar.tokenizeLine('a{ content: "aaaa')); + expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + return expect(tokens[7]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); + }); + + it("knows when a string is line-wrapped", function() { + let lines = grammar.tokenizeLines(`\ +a{ + content: "aaaaa\\\\\\ +aaa"; color: red; +}\ +` + ); + expect(lines[1][4]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[1][5]).toEqual({value: 'aaaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css']}); + expect(lines[1][6]).toEqual({value: '\\\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.css']}); + expect(lines[1][7]).toEqual({value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.newline.css']}); + expect(lines[2][0]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css']}); + expect(lines[2][1]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(lines[2][2]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[2][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + + lines = grammar.tokenizeLines(`\ +a{ + content: 'aaaaa\\\\\\ +aaa'; color: red; +}\ +` + ); + expect(lines[1][4]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(lines[1][5]).toEqual({value: 'aaaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css']}); + expect(lines[1][6]).toEqual({value: '\\\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.css']}); + expect(lines[1][7]).toEqual({value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.newline.css']}); + expect(lines[2][0]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css']}); + expect(lines[2][1]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(lines[2][2]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(lines[2][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + }); + + it('highlights escape sequences inside invalid strings', function() { + let {tokens} = grammar.tokenizeLine('a{ content: "aaa\\"aa'); + expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[7]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); + expect(tokens[8]).toEqual({value: '\\"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css']}); + expect(tokens[9]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); + + ({tokens} = grammar.tokenizeLine("a{ content: 'aaa\\'aa")); + expect(tokens[6]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[7]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); + expect(tokens[8]).toEqual({value: "\\'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css']}); + return expect(tokens[9]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); + }); + + return it('highlights unclosed lines in line-wrapped strings', function() { + const lines = grammar.tokenizeLines(`\ +a{ + content: "aaa\\"aa\\ +aaaa +aaaa; color: red; +}\ +` + ); + expect(lines[1][4]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(lines[1][5]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css']}); + expect(lines[1][6]).toEqual({value: '\\"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.css']}); + expect(lines[1][7]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css']}); + expect(lines[1][8]).toEqual({value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.newline.css']}); + expect(lines[2][0]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); + expect(lines[3][0]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(lines[3][1]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(lines[3][3]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[3][4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(lines[3][6]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(lines[3][7]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); +}); + + describe('comments', function() { + it('tokenises comments inside @import statements', function() { + let {tokens} = grammar.tokenizeLine('@import /* url("name"); */ "1.css";'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[3]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[4]).toEqual({value: ' url("name"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); + expect(tokens[5]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[8]).toEqual({value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); + expect(tokens[9]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine('@import/*";"*/ url("2.css");')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: '";"', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[6]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[8]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[9]).toEqual({value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css']}); + expect(tokens[10]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[12]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + + ({tokens} = grammar.tokenizeLine('@import url("3.css") print /* url(";"); */;')); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); + expect(tokens[3]).toEqual({value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css']}); + expect(tokens[4]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[6]).toEqual({value: '3.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[10]).toEqual({value: 'print', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css']}); + expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[13]).toEqual({value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); + expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + }); + + it('tokenises comments inside @font-face statements', function() { + const {tokens} = grammar.tokenizeLine('@font-face/*"{;}"*/{}'); + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'font-face', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: '"{;}"', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it('tokenizes comments before media queries', function() { + const {tokens} = grammar.tokenizeLine('/* comment */ @media'); + + expect(tokens[0]).toEqual({value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[1]).toEqual({value: ' comment ', scopes: ['source.css', 'comment.block.css']}); + expect(tokens[2]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[4]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + return expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + }); + + it('tokenizes comments after media queries', function() { + const {tokens} = grammar.tokenizeLine('@media/* comment */ ()'); + + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[3]).toEqual({value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + return expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + }); + + it('tokenizes comments inside query lists', function() { + const {tokens} = grammar.tokenizeLine('@media (max-height: 40em/* comment */)'); + + expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); + expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css']}); + expect(tokens[4]).toEqual({value: 'max-height', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css']}); + expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); + expect(tokens[7]).toEqual({value: '40', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); + expect(tokens[8]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); + expect(tokens[9]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[10]).toEqual({value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); + expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + }); + + it('tokenizes inline comments', function() { + const {tokens} = grammar.tokenizeLine('section {border:4px/*padding:1px*/}'); + + expect(tokens[0]).toEqual({value: 'section', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[1]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: 'border', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[5]).toEqual({value: '4', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[6]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[7]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(tokens[8]).toEqual({value: 'padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); + expect(tokens[9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + return it('tokenizes multi-line comments', function() { + const lines = grammar.tokenizeLines(`\ + section { + border:4px /*1px; + padding:1px*/ +}\ +` + ); + + expect(lines[1][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(lines[1][6]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); + expect(lines[1][7]).toEqual({value: '1px;', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); + + expect(lines[2][0]).toEqual({value: ' padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); + expect(lines[2][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + + return expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); +}); + + describe('Animations', () => it('does not confuse animation names with predefined keywords', function() { + const tokens = grammar.tokenizeLines(`\ +.animated { +animation-name: orphan-black; +animation-name: line-scale; +}\ +` + ); + expect(tokens[1][4]).toEqual({value: 'orphan-black', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + return expect(tokens[2][4]).toEqual({value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); +})); + + describe('Transforms', () => it('tokenizes transform functions', function() { + const tokens = grammar.tokenizeLines(`\ +.transformed { +transform: matrix(0, 1.5, -1.5, 0, 0, 100px); +transform: rotate(90deg) translateX(100px) scale(1.5); +}\ +` + ); + expect(tokens[1][1]).toEqual({value: 'transform', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[1][2]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[1][4]).toEqual({value: 'matrix', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); + expect(tokens[1][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(tokens[1][6]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[1][7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[1][12]).toEqual({value: '-1.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[1][22]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[1][23]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[2][4]).toEqual({value: 'rotate', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); + expect(tokens[2][10]).toEqual({value: 'translateX', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); + return expect(tokens[2][16]).toEqual({value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); +})); + + describe("performance regressions", function() { + it("does not hang when tokenizing invalid input preceding an equals sign", function() { + grammar = atom.grammars.grammarForScopeName('source.css'); + const start = Date.now(); + grammar.tokenizeLine(' + [}~${'ÁÂÃÄÅÆÇÈÊËÍÎ'.repeat(100)} +\ +` + ); + return expect(Date.now() - start).toBeLessThan(5000); + }); + }); + + describe("firstLineMatch", function() { + it("recognises Emacs modelines", function() { + let line; + const valid = `\ +#-*- CSS -*- +#-*- mode: CSS -*- +/* -*-css-*- */ +// -*- CSS -*- +/* -*- mode:CSS -*- */ +// -*- font:bar;mode:CSS -*- +// -*- font:bar;mode:CSS;foo:bar; -*- +// -*-font:mode;mode:CSS-*- +// -*- foo:bar mode: css bar:baz -*- +" -*-foo:bar;mode:css;bar:foo-*- "; +" -*-font-mode:foo;mode:css;foo-bar:quux-*-" +"-*-font:x;foo:bar; mode : CsS; bar:foo;foooooo:baaaaar;fo:ba;-*-"; +"-*- font:x;foo : bar ; mode : cSS ; bar : foo ; foooooo:baaaaar;fo:ba-*-";\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +/* --*css-*- */ +/* -*-- CSS -*- +/* -*- -- CSS -*- +/* -*- CSS -;- -*- +// -*- CCSS -*- +// -*- CSS; -*- +// -*- css-stuff -*- +/* -*- model:css -*- +/* -*- indent-mode:css -*- +// -*- font:mode;CSS -*- +// -*- mode: -*- CSS +// -*- mode: I-miss-plain-old-css -*- +// -*-font:mode;mode:css--*-\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + + return it("recognises Vim modelines", function() { + let line; + const valid = `\ +vim: se filetype=css: +# vim: se ft=css: +# vim: set ft=CSS: +# vim: set filetype=CSS: +# vim: ft=CSS +# vim: syntax=CSS +# vim: se syntax=css: +# ex: syntax=CSS +# vim:ft=css +# vim600: ft=css +# vim>600: set ft=css: +# vi:noai:sw=3 ts=6 ft=CSS +# vi::::::::::noai:::::::::::: ft=CSS +# vim:ts=4:sts=4:sw=4:noexpandtab:ft=cSS +# vi:: noai : : : : sw =3 ts =6 ft =Css +# vim: ts=4: pi sts=4: ft=CSS: noexpandtab: sw=4: +# vim: ts=4 sts=4: ft=css noexpandtab: +# vim:noexpandtab sts=4 ft=css ts=4 +# vim:noexpandtab:ft=css +# vim:ts=4:sts=4 ft=css:noexpandtab:\x20 +# vim:noexpandtab titlestring=hi\|there\\\\ ft=css ts=4\ +`; + for (line of Array.from(valid.split(/\n/))) { + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull(); + } + + const invalid = `\ +ex: se filetype=css: +_vi: se filetype=CSS: + vi: se filetype=CSS +# vim set ft=css3 +# vim: soft=css +# vim: clean-syntax=css: +# vim set ft=css: +# vim: setft=CSS: +# vim: se ft=css backupdir=tmp +# vim: set ft=css set cmdheight=1 +# vim:noexpandtab sts:4 ft:CSS ts:4 +# vim:noexpandtab titlestring=hi\\|there\\ ft=CSS ts=4 +# vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=CSS ts=4\ +`; + return (() => { + const result = []; + for (line of Array.from(invalid.split(/\n/))) { + result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull()); + } + return result; + })(); + }); + }); + + return describe("Missing supported properties regressions", function() { + it("recognises place-items property as supported", function() { + const tokens = grammar.tokenizeLines('a { place-items: center center; }'); + expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[0][2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[0][3]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][4]).toEqual({value: 'place-items', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[0][5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[0][6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][7]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[0][8]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it("recognises place-self property as supported", function() { + const tokens = grammar.tokenizeLines('a { place-self: center center; }'); + expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[0][2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[0][3]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][4]).toEqual({value: 'place-self', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[0][5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[0][6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][7]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[0][8]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + it("recognises place-content property as supported", function() { + const tokens = grammar.tokenizeLines('a { place-content: center center; }'); + expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[0][2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[0][3]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][4]).toEqual({value: 'place-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[0][5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[0][6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][7]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[0][8]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); + expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); + + return it("recognises row-gap property as supported", function() { + const tokens = grammar.tokenizeLines('a { row-gap: 5px; }'); + expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.css']}); + expect(tokens[0][2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[0][3]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][4]).toEqual({value: 'row-gap', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(tokens[0][5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[0][6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + expect(tokens[0][7]).toEqual({value: '5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); + expect(tokens[0][8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[0][9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[0][10]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); + return expect(tokens[0][11]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + }); +}); +}); diff --git a/packages/language-gfm/spec/gfm-spec.js b/packages/language-gfm/spec/gfm-spec.js new file mode 100644 index 0000000000..733d14582a --- /dev/null +++ b/packages/language-gfm/spec/gfm-spec.js @@ -0,0 +1,960 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +describe("GitHub Flavored Markdown grammar", function() { + let grammar = null; + + beforeEach(function() { + waitsForPromise(() => atom.packages.activatePackage("language-gfm")); + + return runs(() => grammar = atom.grammars.grammarForScopeName("source.gfm")); + }); + + it("parses the grammar", function() { + expect(grammar).toBeDefined(); + return expect(grammar.scopeName).toBe("source.gfm"); + }); + + it("tokenizes spaces", function() { + const {tokens} = grammar.tokenizeLine(" "); + return expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); +}); + + it("tokenizes horizontal rules", function() { + let {tokens} = grammar.tokenizeLine("***"); + expect(tokens[0]).toEqual({value: "***", scopes: ["source.gfm", "comment.hr.gfm"]}); + + ({tokens} = grammar.tokenizeLine("---")); + expect(tokens[0]).toEqual({value: "---", scopes: ["source.gfm", "comment.hr.gfm"]}); + + ({tokens} = grammar.tokenizeLine("___")); + return expect(tokens[0]).toEqual({value: "___", scopes: ["source.gfm", "comment.hr.gfm"]}); +}); + + it("tokenizes escaped characters", function() { + let {tokens} = grammar.tokenizeLine("\\*"); + expect(tokens[0]).toEqual({value: "\\*", scopes: ["source.gfm", "constant.character.escape.gfm"]}); + + ({tokens} = grammar.tokenizeLine("\\\\")); + expect(tokens[0]).toEqual({value: "\\\\", scopes: ["source.gfm", "constant.character.escape.gfm"]}); + + ({tokens} = grammar.tokenizeLine("\\abc")); + expect(tokens[0]).toEqual({value: "\\a", scopes: ["source.gfm", "constant.character.escape.gfm"]}); + return expect(tokens[1]).toEqual({value: "bc", scopes: ["source.gfm"]}); +}); + + it("tokenizes ***bold italic*** text", function() { + const {tokens} = grammar.tokenizeLine("this is ***bold italic*** text"); + expect(tokens[0]).toEqual({value: "this is ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[2]).toEqual({value: "bold italic", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[3]).toEqual({value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[4]).toEqual({value: " text", scopes: ["source.gfm"]}); + + const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is ***bold\nitalic***!")); + expect(firstLineTokens[0]).toEqual({value: "this is ", scopes: ["source.gfm"]}); + expect(firstLineTokens[1]).toEqual({value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(firstLineTokens[2]).toEqual({value: "bold", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(secondLineTokens[0]).toEqual({value: "italic", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(secondLineTokens[1]).toEqual({value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + return expect(secondLineTokens[2]).toEqual({value: "!", scopes: ["source.gfm"]}); +}); + + it("tokenizes ___bold italic___ text", function() { + const {tokens} = grammar.tokenizeLine("this is ___bold italic___ text"); + expect(tokens[0]).toEqual({value: "this is ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[2]).toEqual({value: "bold italic", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[3]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[4]).toEqual({value: " text", scopes: ["source.gfm"]}); + + const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is ___bold\nitalic___!")); + expect(firstLineTokens[0]).toEqual({value: "this is ", scopes: ["source.gfm"]}); + expect(firstLineTokens[1]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(firstLineTokens[2]).toEqual({value: "bold", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(secondLineTokens[0]).toEqual({value: "italic", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(secondLineTokens[1]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + return expect(secondLineTokens[2]).toEqual({value: "!", scopes: ["source.gfm"]}); +}); + + it("tokenizes **bold** text", function() { + let {tokens} = grammar.tokenizeLine("**bold**"); + expect(tokens[0]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[1]).toEqual({value: "bold", scopes: ["source.gfm", "markup.bold.gfm"]}); + expect(tokens[2]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); + + const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is **not\nbold**!")); + expect(firstLineTokens[0]).toEqual({value: "this is **not", scopes: ["source.gfm"]}); + expect(secondLineTokens[0]).toEqual({value: "bold**!", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("not**bold**")); + expect(tokens[0]).toEqual({value: "not", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[2]).toEqual({value: "bold", scopes: ["source.gfm", "markup.bold.gfm"]}); + return expect(tokens[3]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); +}); + + it("tokenizes __bold__ text", function() { + let {tokens} = grammar.tokenizeLine("____"); + expect(tokens[0]).toEqual({value: "____", scopes: ["source.gfm", "comment.hr.gfm"]}); + + ({tokens} = grammar.tokenizeLine("__bold__")); + expect(tokens[0]).toEqual({value: "__", scopes: [ 'source.gfm', 'markup.bold.gfm', 'punctuation.definition.entity.gfm' ]}); + expect(tokens[1]).toEqual({value: "bold", scopes: ["source.gfm", "markup.bold.gfm"]}); + expect(tokens[2]).toEqual({value: "__", scopes: [ 'source.gfm', 'markup.bold.gfm', 'punctuation.definition.entity.gfm' ]}); + + const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is __not\nbold__!")); + expect(firstLineTokens[0]).toEqual({value: "this is __not", scopes: ["source.gfm"]}); + expect(secondLineTokens[0]).toEqual({value: "bold__!", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("not__bold__")); + return expect(tokens[0]).toEqual({value: "not__bold__", scopes: ["source.gfm"]}); +}); + + it("tokenizes *italic* text", function() { + let {tokens} = grammar.tokenizeLine("**"); + expect(tokens[0]).toEqual({value: "**", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("this is *italic* text")); + expect(tokens[0]).toEqual({value: "this is ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "*", scopes: [ "source.gfm", "markup.italic.gfm", "punctuation.definition.entity.gfm" ]}); + expect(tokens[2]).toEqual({value: "italic", scopes: ["source.gfm", "markup.italic.gfm"]}); + expect(tokens[3]).toEqual({value: "*", scopes: [ "source.gfm", "markup.italic.gfm", "punctuation.definition.entity.gfm" ]}); + expect(tokens[4]).toEqual({value: " text", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("is*italic*")); + expect(tokens[0]).toEqual({value: "is", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "*", scopes: [ "source.gfm", "markup.italic.gfm", "punctuation.definition.entity.gfm" ]}); + expect(tokens[2]).toEqual({value: "italic", scopes: ["source.gfm", "markup.italic.gfm"]}); + expect(tokens[3]).toEqual({value: "*", scopes: [ "source.gfm", "markup.italic.gfm", "punctuation.definition.entity.gfm" ]}); + + ({tokens} = grammar.tokenizeLine("* not italic")); + expect(tokens[0]).toEqual({value: "*", scopes: ["source.gfm", "variable.unordered.list.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[2]).toEqual({value: "not italic", scopes: ["source.gfm"]}); + + const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is *not\nitalic*!")); + expect(firstLineTokens[0]).toEqual({value: "this is *not", scopes: ["source.gfm"]}); + return expect(secondLineTokens[0]).toEqual({value: "italic*!", scopes: ["source.gfm"]}); +}); + + it("tokenizes _italic_ text", function() { + let {tokens} = grammar.tokenizeLine("__"); + expect(tokens[0]).toEqual({value: "__", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("this is _italic_ text")); + expect(tokens[0]).toEqual({value: "this is ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ]}); + expect(tokens[2]).toEqual({value: "italic", scopes: ["source.gfm", "markup.italic.gfm"]}); + expect(tokens[3]).toEqual({value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ]}); + expect(tokens[4]).toEqual({value: " text", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("not_italic_")); + expect(tokens[0]).toEqual({value: "not_italic_", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("not x^{a}_m y^{b}_n italic")); + expect(tokens[0]).toEqual({value: "not x^{a}_m y^{b}_n italic", scopes: ["source.gfm"]}); + + const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is _not\nitalic_!")); + expect(firstLineTokens[0]).toEqual({value: "this is _not", scopes: ["source.gfm"]}); + return expect(secondLineTokens[0]).toEqual({value: "italic_!", scopes: ["source.gfm"]}); +}); + + it("tokenizes ~~strike~~ text", function() { + let {tokens} = grammar.tokenizeLine("~~strike~~"); + expect(tokens[0]).toEqual({value: "~~", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(tokens[1]).toEqual({value: "strike", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(tokens[2]).toEqual({value: "~~", scopes: ["source.gfm", "markup.strike.gfm"]}); + + const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is ~~str\nike~~!")); + expect(firstLineTokens[0]).toEqual({value: "this is ", scopes: ["source.gfm"]}); + expect(firstLineTokens[1]).toEqual({value: "~~", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(firstLineTokens[2]).toEqual({value: "str", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(secondLineTokens[0]).toEqual({value: "ike", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(secondLineTokens[1]).toEqual({value: "~~", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(secondLineTokens[2]).toEqual({value: "!", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("not~~strike~~")); + return expect(tokens[0]).toEqual({value: "not~~strike~~", scopes: ["source.gfm"]}); +}); + + it("tokenizes headings", function() { + let {tokens} = grammar.tokenizeLine("# Heading 1"); + expect(tokens[0]).toEqual({value: "#", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.marker.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.space.gfm"]}); + expect(tokens[2]).toEqual({value: "Heading 1", scopes: ["source.gfm", "markup.heading.heading-1.gfm"]}); + + ({tokens} = grammar.tokenizeLine("## Heading 2")); + expect(tokens[0]).toEqual({value: "##", scopes: ["source.gfm", "markup.heading.heading-2.gfm", "markup.heading.marker.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-2.gfm", "markup.heading.space.gfm"]}); + expect(tokens[2]).toEqual({value: "Heading 2", scopes: ["source.gfm", "markup.heading.heading-2.gfm"]}); + + ({tokens} = grammar.tokenizeLine("### Heading 3")); + expect(tokens[0]).toEqual({value: "###", scopes: ["source.gfm", "markup.heading.heading-3.gfm", "markup.heading.marker.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-3.gfm", "markup.heading.space.gfm"]}); + expect(tokens[2]).toEqual({value: "Heading 3", scopes: ["source.gfm", "markup.heading.heading-3.gfm"]}); + + ({tokens} = grammar.tokenizeLine("#### Heading 4")); + expect(tokens[0]).toEqual({value: "####", scopes: ["source.gfm", "markup.heading.heading-4.gfm", "markup.heading.marker.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-4.gfm", "markup.heading.space.gfm"]}); + expect(tokens[2]).toEqual({value: "Heading 4", scopes: ["source.gfm", "markup.heading.heading-4.gfm"]}); + + ({tokens} = grammar.tokenizeLine("##### Heading 5")); + expect(tokens[0]).toEqual({value: "#####", scopes: ["source.gfm", "markup.heading.heading-5.gfm", "markup.heading.marker.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-5.gfm", "markup.heading.space.gfm"]}); + expect(tokens[2]).toEqual({value: "Heading 5", scopes: ["source.gfm", "markup.heading.heading-5.gfm"]}); + + ({tokens} = grammar.tokenizeLine("###### Heading 6")); + expect(tokens[0]).toEqual({value: "######", scopes: ["source.gfm", "markup.heading.heading-6.gfm", "markup.heading.marker.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-6.gfm", "markup.heading.space.gfm"]}); + return expect(tokens[2]).toEqual({value: "Heading 6", scopes: ["source.gfm", "markup.heading.heading-6.gfm"]}); +}); + + it("tokenizes matches inside of headers", function() { + const {tokens} = grammar.tokenizeLine("# Heading :one:"); + expect(tokens[0]).toEqual({value: "#", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.marker.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.space.gfm"]}); + expect(tokens[2]).toEqual({value: "Heading ", scopes: ["source.gfm", "markup.heading.heading-1.gfm"]}); + expect(tokens[3]).toEqual({value: ":", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.start.gfm"]}); + expect(tokens[4]).toEqual({value: "one", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.word.gfm"]}); + return expect(tokens[5]).toEqual({value: ":", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.end.gfm"]}); +}); + + it("tokenizes an :emoji:", function() { + let {tokens} = grammar.tokenizeLine("this is :no_good:"); + expect(tokens[0]).toEqual({value: "this is ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: ":", scopes: ["source.gfm", "string.emoji.gfm", "string.emoji.start.gfm"]}); + expect(tokens[2]).toEqual({value: "no_good", scopes: ["source.gfm", "string.emoji.gfm", "string.emoji.word.gfm"]}); + expect(tokens[3]).toEqual({value: ":", scopes: ["source.gfm", "string.emoji.gfm", "string.emoji.end.gfm"]}); + + ({tokens} = grammar.tokenizeLine("this is :no good:")); + expect(tokens[0]).toEqual({value: "this is :no good:", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("http://localhost:8080")); + return expect(tokens[0]).toEqual({value: "http://localhost:8080", scopes: ["source.gfm"]}); +}); + + it("tokenizes a ``` code block", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("```"); + expect(tokens[0]).toEqual({value: "```", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); + ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); + expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]}); + ({tokens} = grammar.tokenizeLine("```", ruleStack)); + return expect(tokens[0]).toEqual({value: "```", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); +}); + + it("tokenizes a ~~~ code block", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("~~~"); + expect(tokens[0]).toEqual({value: "~~~", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); + ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); + expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]}); + ({tokens} = grammar.tokenizeLine("~~~", ruleStack)); + return expect(tokens[0]).toEqual({value: "~~~", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); +}); + + it("doesn't tokenise ~`~ as a code block", function() { + const {tokens} = grammar.tokenizeLine("~`~"); + expect(tokens[0]).toEqual({value: '~', scopes: ['source.gfm']}); + expect(tokens[1]).toEqual({value: '`', scopes: ['source.gfm', 'markup.raw.gfm']}); + return expect(tokens[2]).toEqual({value: '~', scopes: ['source.gfm', 'markup.raw.gfm']}); +}); + + it("tokenises code-blocks with borders of differing lengths", function() { + let [firstLineTokens, secondLineTokens, thirdLineTokens] = Array.from(grammar.tokenizeLines("~~~\nfoo bar\n~~~~~~~")); + expect(firstLineTokens[0]).toEqual({value: '~~~', scopes: ['source.gfm', 'markup.raw.gfm', 'support.gfm']}); + expect(secondLineTokens[0]).toEqual({value: 'foo bar', scopes: ['source.gfm', 'markup.raw.gfm']}); + expect(thirdLineTokens[0]).toEqual({value: '~~~~~~~', scopes: ['source.gfm', 'markup.raw.gfm', 'support.gfm']}); + + [firstLineTokens, secondLineTokens, thirdLineTokens] = Array.from(grammar.tokenizeLines("~~~~~~~\nfoo bar\n~~~")); + expect(firstLineTokens[0]).toEqual({value: '~~~~~~~', scopes: ['source.gfm', 'markup.raw.gfm', 'support.gfm']}); + expect(secondLineTokens[0]).toEqual({value: 'foo bar', scopes: ['source.gfm', 'markup.raw.gfm']}); + return expect(thirdLineTokens[0]).toEqual({value: '~~~', scopes: ['source.gfm', 'markup.raw.gfm']}); +}); + + it("tokenizes a ``` code block with trailing whitespace", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("```"); + expect(tokens[0]).toEqual({value: "```", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); + ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); + expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]}); + ({tokens} = grammar.tokenizeLine("``` ", ruleStack)); + return expect(tokens[0]).toEqual({value: "``` ", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); +}); + + it("tokenizes a ~~~ code block with trailing whitespace", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("~~~"); + expect(tokens[0]).toEqual({value: "~~~", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); + ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); + expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]}); + ({tokens} = grammar.tokenizeLine("~~~ ", ruleStack)); + return expect(tokens[0]).toEqual({value: "~~~ ", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); +}); + + it("tokenises a ``` code block with an unknown language", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("``` myLanguage"); + expect(tokens[0]).toEqual({value: '``` myLanguage', scopes: ['source.gfm', 'markup.code.other.gfm', 'support.gfm']}); + + ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); + expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ['source.gfm', 'markup.code.other.gfm', 'source.embedded.mylanguage']}); + + ({tokens} = grammar.tokenizeLine("```", ruleStack)); + return expect(tokens[0]).toEqual({value: '```', scopes: ['source.gfm', 'markup.code.other.gfm', 'support.gfm']}); +}); + + it("tokenizes a ``` code block with a known language", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("``` bash"); + expect(tokens[0]).toEqual({value: "``` bash", scopes: ["source.gfm", "markup.code.shell.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.shell"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```js ")); + expect(tokens[0]).toEqual({value: "```js ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.js"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```JS ")); + expect(tokens[0]).toEqual({value: "```JS ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.js"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```r ")); + expect(tokens[0]).toEqual({value: "```r ", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```properties ")); + expect(tokens[0]).toEqual({value: "```properties ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"]}); + return expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); + }); + + it("tokenizes a Rmarkdown ``` code block", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("```{r}"); + expect(tokens[0]).toEqual({value: "```{r}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```{r,eval=TRUE,cache=FALSE}")); + expect(tokens[0]).toEqual({value: "```{r,eval=TRUE,cache=FALSE}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```{r eval=TRUE,cache=FALSE}")); + expect(tokens[0]).toEqual({value: "```{r eval=TRUE,cache=FALSE}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); + return expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + }); + + it("tokenizes a Rmarkdown ``` code block with whitespace", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("```{r }"); + expect(tokens[0]).toEqual({value: "```{r }", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```{R } ")); + expect(tokens[0]).toEqual({value: "```{R } ", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```{r eval = TRUE, cache = FALSE}")); + expect(tokens[0]).toEqual({value: "```{r eval = TRUE, cache = FALSE}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); + return expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + }); + + it("tokenizes a ~~~ code block with a language", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("~~~ bash"); + expect(tokens[0]).toEqual({value: "~~~ bash", scopes: ["source.gfm", "markup.code.shell.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.shell"); + + ({tokens, ruleStack} = grammar.tokenizeLine("~~~js ")); + expect(tokens[0]).toEqual({value: "~~~js ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.js"); + + ({tokens, ruleStack} = grammar.tokenizeLine("~~~properties ")); + expect(tokens[0]).toEqual({value: "~~~properties ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"]}); + return expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); + }); + + it("tokenizes a ``` code block with a language and trailing whitespace", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("``` bash"); + ({tokens} = grammar.tokenizeLine("``` ", ruleStack)); + expect(tokens[0]).toEqual({value: "``` ", scopes: ["source.gfm", "markup.code.shell.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.shell"); + + ({tokens, ruleStack} = grammar.tokenizeLine("```js ")); + ({tokens} = grammar.tokenizeLine("``` ", ruleStack)); + expect(tokens[0]).toEqual({value: "``` ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"]}); + return expect(ruleStack[1].contentScopeName).toBe("source.embedded.js"); + }); + + it("tokenizes a ~~~ code block with a language and trailing whitespace", function() { + let {tokens, ruleStack} = grammar.tokenizeLine("~~~ bash"); + ({tokens} = grammar.tokenizeLine("~~~ ", ruleStack)); + expect(tokens[0]).toEqual({value: "~~~ ", scopes: ["source.gfm", "markup.code.shell.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.shell"); + + ({tokens, ruleStack} = grammar.tokenizeLine("~~~js ")); + ({tokens} = grammar.tokenizeLine("~~~ ", ruleStack)); + expect(tokens[0]).toEqual({value: "~~~ ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"]}); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.js"); + + ({tokens, ruleStack} = grammar.tokenizeLine("~~~ properties ")); + ({tokens} = grammar.tokenizeLine("~~~ ", ruleStack)); + expect(tokens[0]).toEqual({value: "~~~ ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"]}); + return expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); + }); + + it("tokenizes inline `code` blocks", function() { + let {tokens} = grammar.tokenizeLine("`this` is `code`"); + expect(tokens[0]).toEqual({value: "`", scopes: ["source.gfm", "markup.raw.gfm"]}); + expect(tokens[1]).toEqual({value: "this", scopes: ["source.gfm", "markup.raw.gfm"]}); + expect(tokens[2]).toEqual({value: "`", scopes: ["source.gfm", "markup.raw.gfm"]}); + expect(tokens[3]).toEqual({value: " is ", scopes: ["source.gfm"]}); + expect(tokens[4]).toEqual({value: "`", scopes: ["source.gfm", "markup.raw.gfm"]}); + expect(tokens[5]).toEqual({value: "code", scopes: ["source.gfm", "markup.raw.gfm"]}); + expect(tokens[6]).toEqual({value: "`", scopes: ["source.gfm", "markup.raw.gfm"]}); + + ({tokens} = grammar.tokenizeLine("``")); + expect(tokens[0]).toEqual({value: "`", scopes: ["source.gfm", "markup.raw.gfm"]}); + expect(tokens[1]).toEqual({value: "`", scopes: ["source.gfm", "markup.raw.gfm"]}); + + ({tokens} = grammar.tokenizeLine("``a\\`b``")); + expect(tokens[0]).toEqual({value: "``", scopes: ["source.gfm", "markup.raw.gfm"]}); + expect(tokens[1]).toEqual({value: "a\\`b", scopes: ["source.gfm", "markup.raw.gfm"]}); + return expect(tokens[2]).toEqual({value: "``", scopes: ["source.gfm", "markup.raw.gfm"]}); +}); + + it("tokenizes [links](links)", function() { + const {tokens} = grammar.tokenizeLine("please click [this link](website)"); + expect(tokens[0]).toEqual({value: "please click ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[2]).toEqual({value: "this link", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[4]).toEqual({value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[5]).toEqual({value: "website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + return expect(tokens[6]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); +}); + + it("tokenizes reference [links][links]", function() { + const {tokens} = grammar.tokenizeLine("please click [this link][website]"); + expect(tokens[0]).toEqual({value: "please click ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[2]).toEqual({value: "this link", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[4]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[5]).toEqual({value: "website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + return expect(tokens[6]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); +}); + + it("tokenizes id-less reference [links][]", function() { + const {tokens} = grammar.tokenizeLine("please click [this link][]"); + expect(tokens[0]).toEqual({value: "please click ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[2]).toEqual({value: "this link", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[4]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + return expect(tokens[5]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); +}); + + it("tokenizes [link]: footers", function() { + const {tokens} = grammar.tokenizeLine("[aLink]: http://website"); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[1]).toEqual({value: "aLink", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[2]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[3]).toEqual({value: ":", scopes: ["source.gfm", "link", "punctuation.separator.key-value.gfm"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "link"]}); + return expect(tokens[5]).toEqual({value: "http://website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); +}); + + it("tokenizes [link]: ", function() { + const {tokens} = grammar.tokenizeLine("[aLink]: "); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[1]).toEqual({value: "aLink", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[2]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[3]).toEqual({value: ": <", scopes: ["source.gfm", "link"]}); + expect(tokens[4]).toEqual({value: "http://website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + return expect(tokens[5]).toEqual({value: ">", scopes: ["source.gfm", "link"]}); +}); + + it("tokenizes [![links](links)](links)", function() { + const {tokens} = grammar.tokenizeLine("[![title](image)](link)"); + expect(tokens[0]).toEqual({value: "[!", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[1]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[2]).toEqual({value: "title", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[4]).toEqual({value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[5]).toEqual({value: "image", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + expect(tokens[6]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[7]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[8]).toEqual({value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[9]).toEqual({value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + return expect(tokens[10]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); +}); + + it("tokenizes [![links](links)][links]", function() { + const {tokens} = grammar.tokenizeLine("[![title](image)][link]"); + expect(tokens[0]).toEqual({value: "[!", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[1]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[2]).toEqual({value: "title", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[4]).toEqual({value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[5]).toEqual({value: "image", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + expect(tokens[6]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[7]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[8]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[9]).toEqual({value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + return expect(tokens[10]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); +}); + + it("tokenizes [![links][links]](links)", function() { + const {tokens} = grammar.tokenizeLine("[![title][image]](link)"); + expect(tokens[0]).toEqual({value: "[!", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[1]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[2]).toEqual({value: "title", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[4]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[5]).toEqual({value: "image", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + expect(tokens[6]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[7]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[8]).toEqual({value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[9]).toEqual({value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + return expect(tokens[10]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); +}); + + it("tokenizes [![links][links]][links]", function() { + const {tokens} = grammar.tokenizeLine("[![title][image]][link]"); + expect(tokens[0]).toEqual({value: "[!", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[1]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[2]).toEqual({value: "title", scopes: ["source.gfm", "link", "entity.gfm"]}); + expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[4]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[5]).toEqual({value: "image", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + expect(tokens[6]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[7]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[8]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); + expect(tokens[9]).toEqual({value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + return expect(tokens[10]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); +}); + + it("tokenizes mentions", function() { + let {tokens} = grammar.tokenizeLine("sentence with no space before@name "); + expect(tokens[0]).toEqual({value: "sentence with no space before@name ", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("@name '@name' @name's @name. @name, (@name) [@name]")); + expect(tokens[0]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[1]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[2]).toEqual({value: " '", scopes: ["source.gfm"]}); + expect(tokens[3]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[4]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[5]).toEqual({value: "' ", scopes: ["source.gfm"]}); + expect(tokens[6]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[7]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[8]).toEqual({value: "'s ", scopes: ["source.gfm"]}); + expect(tokens[9]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[10]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[11]).toEqual({value: ". ", scopes: ["source.gfm"]}); + expect(tokens[12]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[13]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[14]).toEqual({value: ", (", scopes: ["source.gfm"]}); + expect(tokens[15]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[16]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[17]).toEqual({value: ") [", scopes: ["source.gfm"]}); + expect(tokens[18]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[19]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[20]).toEqual({value: "]", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine('"@name"')); + expect(tokens[0]).toEqual({value: '"', scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[2]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[3]).toEqual({value: '"', scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("sentence with a space before @name/ and an invalid symbol after")); + expect(tokens[0]).toEqual({value: "sentence with a space before @name/ and an invalid symbol after", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("sentence with a space before @name that continues")); + expect(tokens[0]).toEqual({value: "sentence with a space before ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[2]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[3]).toEqual({value: " that continues", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("* @name at the start of an unordered list")); + expect(tokens[0]).toEqual({value: "*", scopes: ["source.gfm", "variable.unordered.list.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[2]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[3]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[4]).toEqual({value: " at the start of an unordered list", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("a username @1337_hubot with numbers, letters and underscores")); + expect(tokens[0]).toEqual({value: "a username ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[2]).toEqual({value: "1337_hubot", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[3]).toEqual({value: " with numbers, letters and underscores", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("a username @1337-hubot with numbers, letters and hyphens")); + expect(tokens[0]).toEqual({value: "a username ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[2]).toEqual({value: "1337-hubot", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[3]).toEqual({value: " with numbers, letters and hyphens", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("@name at the start of a line")); + expect(tokens[0]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[1]).toEqual({value: "name", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[2]).toEqual({value: " at the start of a line", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("any email like you@domain.com shouldn't mistakenly be matched as a mention")); + expect(tokens[0]).toEqual({value: "any email like you@domain.com shouldn't mistakenly be matched as a mention", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("@person's")); + expect(tokens[0]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[1]).toEqual({value: "person", scopes: ["source.gfm", "string.username.gfm"]}); + expect(tokens[2]).toEqual({value: "'s", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("@person;")); + expect(tokens[0]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); + expect(tokens[1]).toEqual({value: "person", scopes: ["source.gfm", "string.username.gfm"]}); + return expect(tokens[2]).toEqual({value: ";", scopes: ["source.gfm"]}); +}); + + it("tokenizes issue numbers", function() { + let {tokens} = grammar.tokenizeLine("sentence with no space before#12 "); + expect(tokens[0]).toEqual({value: "sentence with no space before#12 ", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine(" #101 '#101' #101's #101. #101, (#101) [#101]")); + expect(tokens[1]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[2]).toEqual({value: "101", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[3]).toEqual({value: " '", scopes: ["source.gfm"]}); + expect(tokens[4]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[5]).toEqual({value: "101", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[6]).toEqual({value: "' ", scopes: ["source.gfm"]}); + expect(tokens[7]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[8]).toEqual({value: "101", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[9]).toEqual({value: "'s ", scopes: ["source.gfm"]}); + expect(tokens[10]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[11]).toEqual({value: "101", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[12]).toEqual({value: ". ", scopes: ["source.gfm"]}); + expect(tokens[13]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[14]).toEqual({value: "101", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[15]).toEqual({value: ", (", scopes: ["source.gfm"]}); + expect(tokens[16]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[17]).toEqual({value: "101", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[18]).toEqual({value: ") [", scopes: ["source.gfm"]}); + expect(tokens[19]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[20]).toEqual({value: "101", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[21]).toEqual({value: "]", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine('"#101"')); + expect(tokens[0]).toEqual({value: '"', scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[2]).toEqual({value: "101", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[3]).toEqual({value: '"', scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("sentence with a space before #123i and a character after")); + expect(tokens[0]).toEqual({value: "sentence with a space before #123i and a character after", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine("sentence with a space before #123 that continues")); + expect(tokens[0]).toEqual({value: "sentence with a space before ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[2]).toEqual({value: "123", scopes: ["source.gfm", "string.issue.number.gfm"]}); + expect(tokens[3]).toEqual({value: " that continues", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine(" #123's")); + expect(tokens[1]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); + expect(tokens[2]).toEqual({value: "123", scopes: ["source.gfm", "string.issue.number.gfm"]}); + return expect(tokens[3]).toEqual({value: "'s", scopes: ["source.gfm"]}); +}); + + it("tokenizes unordered lists", function() { + let {tokens} = grammar.tokenizeLine("*Item 1"); + expect(tokens[0]).not.toEqual({value: "*Item 1", scopes: ["source.gfm", "variable.unordered.list.gfm"]}); + + ({tokens} = grammar.tokenizeLine(" * Item 1")); + expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "*", scopes: ["source.gfm", "variable.unordered.list.gfm"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[3]).toEqual({value: "Item 1", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine(" + Item 2")); + expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "+", scopes: ["source.gfm", "variable.unordered.list.gfm"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[3]).toEqual({value: "Item 2", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine(" - Item 3")); + expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "-", scopes: ["source.gfm", "variable.unordered.list.gfm"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.gfm"]}); + return expect(tokens[3]).toEqual({value: "Item 3", scopes: ["source.gfm"]}); +}); + + it("tokenizes ordered lists", function() { + let {tokens} = grammar.tokenizeLine("1.First Item"); + expect(tokens[0]).toEqual({value: "1.First Item", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine(" 1. First Item")); + expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "1.", scopes: ["source.gfm", "variable.ordered.list.gfm"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[3]).toEqual({value: "First Item", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine(" 10. Tenth Item")); + expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "10.", scopes: ["source.gfm", "variable.ordered.list.gfm"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[3]).toEqual({value: "Tenth Item", scopes: ["source.gfm"]}); + + ({tokens} = grammar.tokenizeLine(" 111. Hundred and eleventh item")); + expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "111.", scopes: ["source.gfm", "variable.ordered.list.gfm"]}); + expect(tokens[2]).toEqual({value: " ", scopes: ["source.gfm"]}); + return expect(tokens[3]).toEqual({value: "Hundred and eleventh item", scopes: ["source.gfm"]}); +}); + + it("tokenizes > quoted text", function() { + const {tokens} = grammar.tokenizeLine("> Quotation :+1:"); + expect(tokens[0]).toEqual({value: ">", scopes: ["source.gfm", "comment.quote.gfm", "support.quote.gfm"]}); + return expect(tokens[1]).toEqual({value: " Quotation :+1:", scopes: ["source.gfm", "comment.quote.gfm"]}); +}); + + it("tokenizes HTML entities", function() { + const {tokens} = grammar.tokenizeLine("™ ™ &a1; ³"); + expect(tokens[0]).toEqual({value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[1]).toEqual({value: "trade", scopes: ["source.gfm", "constant.character.entity.gfm"]}); + expect(tokens[2]).toEqual({value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + + expect(tokens[3]).toEqual({value: " ", scopes: ["source.gfm"]}); + + expect(tokens[4]).toEqual({value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[5]).toEqual({value: "#8482", scopes: ["source.gfm", "constant.character.entity.gfm"]}); + expect(tokens[6]).toEqual({value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + + expect(tokens[7]).toEqual({value: " ", scopes: ["source.gfm"]}); + + expect(tokens[8]).toEqual({value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[9]).toEqual({value: "a1", scopes: ["source.gfm", "constant.character.entity.gfm"]}); + expect(tokens[10]).toEqual({value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + + expect(tokens[11]).toEqual({value: " ", scopes: ["source.gfm"]}); + + expect(tokens[12]).toEqual({value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[13]).toEqual({value: "#xb3", scopes: ["source.gfm", "constant.character.entity.gfm"]}); + return expect(tokens[14]).toEqual({value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); +}); + + it("tokenizes HTML entities in *italic* text", function() { + let {tokens} = grammar.tokenizeLine("*™ ™ ³*"); + expect(tokens[0]).toEqual({value: "*", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ]}); + expect(tokens[1]).toEqual({value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[2]).toEqual({value: "trade", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[3]).toEqual({value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "markup.italic.gfm"]}); + expect(tokens[5]).toEqual({value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[6]).toEqual({value: "#8482", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[7]).toEqual({value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.gfm", "markup.italic.gfm"]}); + expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[12]).toEqual({value: "*", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ]}); + + ({tokens} = grammar.tokenizeLine("_™ ™ ³_")); + expect(tokens[0]).toEqual({value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ]}); + expect(tokens[1]).toEqual({value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[2]).toEqual({value: "trade", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[3]).toEqual({value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "markup.italic.gfm"]}); + expect(tokens[5]).toEqual({value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[6]).toEqual({value: "#8482", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[7]).toEqual({value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.gfm", "markup.italic.gfm"]}); + expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + return expect(tokens[12]).toEqual({value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ]}); +}); + + it("tokenizes HTML entities in **bold** text", function() { + let {tokens} = grammar.tokenizeLine("**™ ™ ³**"); + expect(tokens[0]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[1]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[2]).toEqual({value: "trade", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"]}); + expect(tokens[3]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "markup.bold.gfm"]}); + expect(tokens[5]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[6]).toEqual({value: "#8482", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"]}); + expect(tokens[7]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.gfm", "markup.bold.gfm"]}); + expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"]}); + expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[12]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); + + ({tokens} = grammar.tokenizeLine("__™ ™ ³__")); + expect(tokens[0]).toEqual({value: "__", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[1]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[2]).toEqual({value: "trade", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"]}); + expect(tokens[3]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "markup.bold.gfm"]}); + expect(tokens[5]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[6]).toEqual({value: "#8482", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"]}); + expect(tokens[7]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.gfm", "markup.bold.gfm"]}); + expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"]}); + expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + return expect(tokens[12]).toEqual({value: "__", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); +}); + + it("tokenizes HTML entities in ***bold italic*** text", function() { + let {tokens} = grammar.tokenizeLine("***™ ™ ³***"); + expect(tokens[0]).toEqual({value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[1]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[2]).toEqual({value: "trade", scopes: [ "source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm" ]}); + expect(tokens[3]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[5]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[6]).toEqual({value: "#8482", scopes: [ "source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm" ]}); + expect(tokens[7]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[12]).toEqual({value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + + ({tokens} = grammar.tokenizeLine("___™ ™ ³___")); + expect(tokens[0]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[1]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[2]).toEqual({value: "trade", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[3]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[5]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[6]).toEqual({value: "#8482", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[7]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"]}); + return expect(tokens[12]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); +}); + + it("tokenizes HTML entities in strikethrough text", function() { + const {tokens} = grammar.tokenizeLine("~~™ ™ ³~~"); + expect(tokens[0]).toEqual({value: "~~", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(tokens[1]).toEqual({value: "&", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[2]).toEqual({value: "trade", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm"]}); + expect(tokens[3]).toEqual({value: ";", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(tokens[5]).toEqual({value: "&", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[6]).toEqual({value: "#8482", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm"]}); + expect(tokens[7]).toEqual({value: ";", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[8]).toEqual({value: " ", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm"]}); + expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + return expect(tokens[12]).toEqual({value: "~~", scopes: ["source.gfm", "markup.strike.gfm"]}); +}); + + it("tokenizes HTML comments", function() { + const {tokens} = grammar.tokenizeLine(""); + expect(tokens[0]).toEqual({value: "", scopes: ["source.gfm", "comment.block.gfm", "punctuation.definition.comment.gfm"]}); +}); + + it("tokenizes YAML front matter", function() { + const [firstLineTokens, secondLineTokens, thirdLineTokens] = Array.from(grammar.tokenizeLines(`\ +--- +front: matter +---\ +` + )); + + expect(firstLineTokens[0]).toEqual({value: "---", scopes: ["source.gfm", "front-matter.yaml.gfm", "comment.hr.gfm"]}); + expect(secondLineTokens[0]).toEqual({value: "front: matter", scopes: ["source.gfm", "front-matter.yaml.gfm"]}); + return expect(thirdLineTokens[0]).toEqual({value: "---", scopes: ["source.gfm", "front-matter.yaml.gfm", "comment.hr.gfm"]}); +}); + + it("tokenizes linebreaks", function() { + const {tokens} = grammar.tokenizeLine("line "); + expect(tokens[0]).toEqual({value: "line", scopes: ["source.gfm"]}); + return expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "linebreak.gfm"]}); +}); + + it("tokenizes tables", function() { + let emptyLineTokens, headingTokens; + let [headerTokens, alignTokens, contentTokens] = Array.from(grammar.tokenizeLines(`\ +| Column 1 | Column 2 | +|:----------|:---------:| +| Content 1 | Content 2 |\ +` + )); + + // Header line + expect(headerTokens[0]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"]}); + expect(headerTokens[1]).toEqual({value: " Column 1 ", scopes: ["source.gfm", "table.gfm"]}); + expect(headerTokens[2]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.inner"]}); + expect(headerTokens[3]).toEqual({value: " Column 2 ", scopes: ["source.gfm", "table.gfm"]}); + expect(headerTokens[4]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"]}); + + // Alignment line + expect(alignTokens[0]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"]}); + expect(alignTokens[1]).toEqual({value: ":", scopes: ["source.gfm", "table.gfm", "border.alignment"]}); + expect(alignTokens[2]).toEqual({value: "----------", scopes: ["source.gfm", "table.gfm", "border.header"]}); + expect(alignTokens[3]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.inner"]}); + expect(alignTokens[4]).toEqual({value: ":", scopes: ["source.gfm", "table.gfm", "border.alignment"]}); + expect(alignTokens[5]).toEqual({value: "---------", scopes: ["source.gfm", "table.gfm", "border.header"]}); + expect(alignTokens[6]).toEqual({value: ":", scopes: ["source.gfm", "table.gfm", "border.alignment"]}); + expect(alignTokens[7]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"]}); + + // Content line + expect(contentTokens[0]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"]}); + expect(contentTokens[1]).toEqual({value: " Content 1 ", scopes: ["source.gfm", "table.gfm"]}); + expect(contentTokens[2]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.inner"]}); + expect(contentTokens[3]).toEqual({value: " Content 2 ", scopes: ["source.gfm", "table.gfm"]}); + expect(contentTokens[4]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"]}); + + [headerTokens, emptyLineTokens, headingTokens] = Array.from(grammar.tokenizeLines(`\ +| Column 1 | Column 2\t + +# Heading\ +` + )); + + expect(headerTokens[0]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"]}); + expect(headerTokens[1]).toEqual({value: " Column 1 ", scopes: ["source.gfm", "table.gfm"]}); + expect(headerTokens[2]).toEqual({value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.inner"]}); + expect(headerTokens[3]).toEqual({value: " Column 2", scopes: ["source.gfm", "table.gfm"]}); + expect(headerTokens[4]).toEqual({value: "\t", scopes: ["source.gfm", "table.gfm"]}); + + expect(headingTokens[0]).toEqual({value: "#", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.marker.gfm"]}); + expect(headingTokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.space.gfm"]}); + return expect(headingTokens[2]).toEqual({value: "Heading", scopes: ["source.gfm", "markup.heading.heading-1.gfm"]}); +}); + + return it("tokenizes criticmarkup", function() { + const [addToken, delToken, hlToken, subToken] = Array.from(grammar.tokenizeLines(`\ +Add{++ some text++} +Delete{-- some text--} +Highlight {==some text==}{>>with comment<<} +Replace {~~this~>by that~~}\ +` + )); + // Addition + expect(addToken[0]).toEqual({value: "Add", scopes: ["source.gfm"]}); + expect(addToken[1]).toEqual({value: "{++", scopes: ["source.gfm", "markup.inserted.critic.gfm.addition", "punctuation.definition.inserted.critic.gfm.addition.marker"]}); + expect(addToken[2]).toEqual({value: " some text", scopes: ["source.gfm", "markup.inserted.critic.gfm.addition"]}); + expect(addToken[3]).toEqual({value: "++}", scopes: ["source.gfm", "markup.inserted.critic.gfm.addition", "punctuation.definition.inserted.critic.gfm.addition.marker"]}); + // Deletion + expect(delToken[0]).toEqual({value: "Delete", scopes: ["source.gfm"]}); + expect(delToken[1]).toEqual({value: "{--", scopes: ["source.gfm", "markup.deleted.critic.gfm.deletion", "punctuation.definition.deleted.critic.gfm.deletion.marker"]}); + expect(delToken[2]).toEqual({value: " some text", scopes: ["source.gfm", "markup.deleted.critic.gfm.deletion"]}); + expect(delToken[3]).toEqual({value: "--}", scopes: ["source.gfm", "markup.deleted.critic.gfm.deletion", "punctuation.definition.deleted.critic.gfm.deletion.marker"]}); + // Comment and highlight + expect(hlToken[0]).toEqual({value: "Highlight ", scopes: ["source.gfm"]}); + expect(hlToken[1]).toEqual({value: "{==", scopes: ["source.gfm", "critic.gfm.highlight", "critic.gfm.highlight.marker"]}); + expect(hlToken[2]).toEqual({value: "some text", scopes: ["source.gfm", "critic.gfm.highlight"]}); + expect(hlToken[3]).toEqual({value: "==}", scopes: ["source.gfm", "critic.gfm.highlight", "critic.gfm.highlight.marker"]}); + expect(hlToken[4]).toEqual({value: "{>>", scopes: ["source.gfm", "critic.gfm.comment", "critic.gfm.comment.marker"]}); + expect(hlToken[5]).toEqual({value: "with comment", scopes: ["source.gfm", "critic.gfm.comment"]}); + expect(hlToken[6]).toEqual({value: "<<}", scopes: ["source.gfm", "critic.gfm.comment", "critic.gfm.comment.marker"]}); + // Replace + expect(subToken[0]).toEqual({value: "Replace ", scopes: ["source.gfm"]}); + expect(subToken[1]).toEqual({value: "{~~", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.marker"]}); + expect(subToken[2]).toEqual({value: "this", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution"]}); + expect(subToken[3]).toEqual({value: "~>", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.operator"]}); + expect(subToken[4]).toEqual({value: "by that", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution"]}); + return expect(subToken[5]).toEqual({value: "~~}", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.marker"]}); +}); +}); diff --git a/packages/language-git/spec/git-spec.js b/packages/language-git/spec/git-spec.js new file mode 100644 index 0000000000..ed04464d0b --- /dev/null +++ b/packages/language-git/spec/git-spec.js @@ -0,0 +1,212 @@ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +describe("Git grammars", function() { + let grammar = null; + + beforeEach(() => waitsForPromise(() => atom.packages.activatePackage("language-git"))); + + describe("Git configs", function() { + beforeEach(() => grammar = atom.grammars.grammarForScopeName("source.git-config")); + + return it("parses the Git config grammar", function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe("source.git-config"); + }); + }); + + describe("Git commit messages", function() { + const scopeNormal = ['text.git-commit', 'meta.scope.message.git-commit']; + + const scopeLeadingLowercase = + ['text.git-commit', 'meta.scope.message.git-commit', 'invalid.illegal.first-char-should-be-uppercase.git-commit']; + + const scopeTrailingPeriod = + ['text.git-commit', 'meta.scope.message.git-commit', 'invalid.illegal.subject-no-trailing-period.git-commit']; + + const scopeLineOver50 = ['text.git-commit', 'meta.scope.message.git-commit', 'invalid.deprecated.line-too-long.git-commit']; + + const scopeLineOver72 = ['text.git-commit', 'meta.scope.message.git-commit', 'invalid.illegal.line-too-long.git-commit']; + + beforeEach(() => grammar = atom.grammars.grammarForScopeName("text.git-commit")); + + it("parses the Git commit message grammar", function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe("text.git-commit"); + }); + + it("highlights subject lines of less than 50 chars correctly", function() { + let {tokens} = grammar.tokenizeLine("123456789012345678901234567890", null, true); + expect(tokens[0]).toEqual({value: '123456789012345678901234567890', scopes: scopeNormal}); + + ({tokens} = grammar.tokenizeLine("a23456789012345678901234567890", null, true)); + expect(tokens[0]).toEqual({value: 'a', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '23456789012345678901234567890', scopes: scopeNormal}); + + ({tokens} = grammar.tokenizeLine("12345678901234567890123456789.", null, true)); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + + ({tokens} = grammar.tokenizeLine("b2345678901234567890123456789.", null, true)); + expect(tokens[0]).toEqual({value: 'b', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789', scopes: scopeNormal}); + return expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + }); + + it("highlights subject lines of 50 chars correctly", function() { + let {tokens} = grammar.tokenizeLine("12345678901234567890123456789012345678901234567890", null, true); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + + ({tokens} = grammar.tokenizeLine("c2345678901234567890123456789012345678901234567890", null, true)); + expect(tokens[0]).toEqual({value: 'c', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + + ({tokens} = grammar.tokenizeLine("1234567890123456789012345678901234567890123456789.", null, true)); + expect(tokens[0]).toEqual({value: '1234567890123456789012345678901234567890123456789', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + + ({tokens} = grammar.tokenizeLine("d234567890123456789012345678901234567890123456789.", null, true)); + expect(tokens[0]).toEqual({value: 'd', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '234567890123456789012345678901234567890123456789', scopes: scopeNormal}); + return expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + }); + + it("highlights subject lines of 51 chars correctly", function() { + let {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901", null, true); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '1', scopes: scopeLineOver50}); + + ({tokens} = grammar.tokenizeLine("e23456789012345678901234567890123456789012345678901", null, true)); + expect(tokens[0]).toEqual({value: 'e', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[2]).toEqual({value: '1', scopes: scopeLineOver50}); + + ({tokens} = grammar.tokenizeLine("12345678901234567890123456789012345678901234567890.", null, true)); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + + ({tokens} = grammar.tokenizeLine("f2345678901234567890123456789012345678901234567890.", null, true)); + expect(tokens[0]).toEqual({value: 'f', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + return expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + }); + + it("highlights subject lines of 72 chars correctly", function() { + let {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012", null, true); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '123456789012345678901', scopes: scopeLineOver50}); + expect(tokens[2]).toEqual({value: '2', scopes: scopeLineOver50}); + + ({tokens} = grammar.tokenizeLine("g23456789012345678901234567890123456789012345678901234567890123456789012", null, true)); + expect(tokens[0]).toEqual({value: 'g', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[2]).toEqual({value: '123456789012345678901', scopes: scopeLineOver50}); + expect(tokens[3]).toEqual({value: '2', scopes: scopeLineOver50}); + + ({tokens} = grammar.tokenizeLine("12345678901234567890123456789012345678901234567890123456789012345678901.", null, true)); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '123456789012345678901', scopes: scopeLineOver50}); + expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + + ({tokens} = grammar.tokenizeLine("h2345678901234567890123456789012345678901234567890123456789012345678901.", null, true)); + expect(tokens[0]).toEqual({value: 'h', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[2]).toEqual({value: '123456789012345678901', scopes: scopeLineOver50}); + return expect(tokens[3]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + }); + + it("highlights subject lines of 73 chars correctly", function() { + let {tokens} = grammar.tokenizeLine("1234567890123456789012345678901234567890123456789012345678901234567890123", null, true); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); + expect(tokens[2]).toEqual({value: '3', scopes: scopeLineOver72}); + + ({tokens} = grammar.tokenizeLine("i234567890123456789012345678901234567890123456789012345678901234567890123", null, true)); + expect(tokens[0]).toEqual({value: 'i', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[2]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); + expect(tokens[3]).toEqual({value: '3', scopes: scopeLineOver72}); + + ({tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012.", null, true)); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); + expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + + ({tokens} = grammar.tokenizeLine("j23456789012345678901234567890123456789012345678901234567890123456789012.", null, true)); + expect(tokens[0]).toEqual({value: 'j', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[2]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); + return expect(tokens[3]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + }); + + return it("highlights subject lines of over 73 chars correctly", function() { + let {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012345678", null, true); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); + expect(tokens[2]).toEqual({value: '345678', scopes: scopeLineOver72}); + + ({tokens} = grammar.tokenizeLine("k23456789012345678901234567890123456789012345678901234567890123456789012345678", null, true)); + expect(tokens[0]).toEqual({value: 'k', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[2]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); + expect(tokens[3]).toEqual({value: '345678', scopes: scopeLineOver72}); + + ({tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012345678.", null, true)); + expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[1]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); + expect(tokens[2]).toEqual({value: '345678', scopes: scopeLineOver72}); + expect(tokens[3]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + + ({tokens} = grammar.tokenizeLine("m23456789012345678901234567890123456789012345678901234567890123456789012345678.", null, true)); + expect(tokens[0]).toEqual({value: 'm', scopes: scopeLeadingLowercase}); + expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); + expect(tokens[2]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); + expect(tokens[3]).toEqual({value: '345678', scopes: scopeLineOver72}); + return expect(tokens[4]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + }); + }); + + return describe("Git rebases", function() { + beforeEach(() => grammar = atom.grammars.grammarForScopeName("text.git-rebase")); + + it("parses the Git rebase message grammar", function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe("text.git-rebase"); + }); + + for (var cmd of ["pick", "p", "reword", "r", "edit", "e", "squash", "s", "fixup", "f", "drop", "d"]) { + it(`parses the ${cmd} command`, function() { + const {tokens} = grammar.tokenizeLine(`${cmd} c0ffeee This is commit message`); + + expect(tokens[0]).toEqual({value: cmd, scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "support.function.git-rebase"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["text.git-rebase", "meta.commit-command.git-rebase"]}); + expect(tokens[2]).toEqual({value: "c0ffeee", scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "constant.sha.git-rebase"]}); + expect(tokens[3]).toEqual({value: " ", scopes: ["text.git-rebase", "meta.commit-command.git-rebase"]}); + return expect(tokens[4]).toEqual({value: "This is commit message", scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "meta.commit-message.git-rebase"]}); + }); + } + + it("parses the exec command", function() { + let {tokens} = grammar.tokenizeLine("exec"); + + expect(tokens[0]).toEqual({value: "exec", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"]}); + + ({tokens} = grammar.tokenizeLine("x")); + + return expect(tokens[0]).toEqual({value: "x", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"]}); + }); + + return it("includes language-shellscript highlighting when using the exec command", function() { + waitsForPromise(() => atom.packages.activatePackage("language-shellscript")); + + return runs(function() { + const {tokens} = grammar.tokenizeLine("exec echo 'Hello World'"); + + expect(tokens[0]).toEqual({value: "exec", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["text.git-rebase", "meta.exec-command.git-rebase"]}); + return expect(tokens[2]).toEqual({value: "echo", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.builtin.shell"]});}); + }); +}); +}); diff --git a/packages/language-go/spec/go-spec.js b/packages/language-go/spec/go-spec.js new file mode 100644 index 0000000000..72c6b68695 --- /dev/null +++ b/packages/language-go/spec/go-spec.js @@ -0,0 +1,1229 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +describe('Go grammar', function() { + let grammar = null; + + beforeEach(function() { + atom.config.set('core.useTreeSitterParsers', false); + + waitsForPromise(() => atom.packages.activatePackage('language-go')); + + return runs(() => grammar = atom.grammars.grammarForScopeName('source.go')); + }); + + it('parses the grammar', function() { + expect(grammar).toBeTruthy(); + return expect(grammar.scopeName).toBe('source.go'); + }); + + it('tokenizes comments', function() { + let {tokens} = grammar.tokenizeLine('// I am a comment'); + expect(tokens[0].value).toEqual('//'); + expect(tokens[0].scopes).toEqual(['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']); + expect(tokens[1].value).toEqual(' I am a comment'); + expect(tokens[1].scopes).toEqual(['source.go', 'comment.line.double-slash.go']); + + tokens = grammar.tokenizeLines('/*\nI am a comment\n*/'); + expect(tokens[0][0].value).toEqual('/*'); + expect(tokens[0][0].scopes).toEqual(['source.go', 'comment.block.go', 'punctuation.definition.comment.go']); + expect(tokens[1][0].value).toEqual('I am a comment'); + expect(tokens[1][0].scopes).toEqual(['source.go', 'comment.block.go']); + expect(tokens[2][0].value).toEqual('*/'); + return expect(tokens[2][0].scopes).toEqual(['source.go', 'comment.block.go', 'punctuation.definition.comment.go']); +}); + + it('tokenizes comments in imports', function() { + const lines = grammar.tokenizeLines(`\ +import ( + //"fmt" + "os" // comment + // comment! +)\ +` + ); + expect(lines[1][1]).toEqual({value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']}); + expect(lines[2][5]).toEqual({value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']}); + return expect(lines[3][1]).toEqual({value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']}); +}); + + it('tokenizes strings', function() { + const delims = { + 'string.quoted.double.go': '"', + 'string.quoted.raw.go': '`' + }; + + return (() => { + const result = []; + for (let scope in delims) { + const delim = delims[scope]; + const {tokens} = grammar.tokenizeLine(delim + 'I am a string' + delim); + expect(tokens[0].value).toEqual(delim); + expect(tokens[0].scopes).toEqual(['source.go', scope, 'punctuation.definition.string.begin.go']); + expect(tokens[1].value).toEqual('I am a string'); + expect(tokens[1].scopes).toEqual(['source.go', scope]); + expect(tokens[2].value).toEqual(delim); + result.push(expect(tokens[2].scopes).toEqual(['source.go', scope, 'punctuation.definition.string.end.go'])); + } + return result; + })(); +}); + + it('tokenizes placeholders in strings', function() { + // Taken from go/src/pkg/fmt/fmt_test.go + const verbs = [ + '%# x', '%-5s', '%5s', '%05s', '%.5s', '%10.1q', '%10v', '%-10v', '%.0d', + '%.d', '%+07.2f', '%0100d', '%0.100f', '%#064x', '%+.3F', '%-#20.8x', + '%[1]d', '%[2]*[1]d', '%[3]*.[2]*[1]f', '%[3]*.[2]f', '%3.[2]d', '%.[2]d', + '%-+[1]x', '%d', '%-d', '%+d', '%#d', '% d', '%0d', '%1.2d', '%-1.2d', + '%+1.2d', '%-+1.2d', '%*d', '%.*d', '%*.*d', '%0*d', '%-*d' + ]; + + return (() => { + const result = []; + for (let verb of Array.from(verbs)) { + const {tokens} = grammar.tokenizeLine('"' + verb + '"'); + expect(tokens[0].value).toEqual('"', + expect(tokens[0].scopes).toEqual(['source.go', 'string.quoted.double.go', 'punctuation.definition.string.begin.go'])); + expect(tokens[1].value).toEqual(verb); + expect(tokens[1].scopes).toEqual(['source.go', 'string.quoted.double.go', 'constant.other.placeholder.go']); + result.push(expect(tokens[2].value).toEqual('"', + expect(tokens[2].scopes).toEqual(['source.go', 'string.quoted.double.go', 'punctuation.definition.string.end.go']))); + } + return result; + })(); +}); + + it('tokenizes character escapes in strings', function() { + let tokens; + const escapes = [ + '\\a', '\\b', '\\f', '\\n', '\\r', '\\t', '\\v', '\\\\', + '\\000', '\\007', '\\377', '\\x07', '\\xff', '\\u12e4', '\\U00101234' + ]; + + for (let escape of Array.from(escapes)) { + ({tokens} = grammar.tokenizeLine('"' + escape + '"')); + expect(tokens[1].value).toEqual(escape); + expect(tokens[1].scopes).toEqual(['source.go', 'string.quoted.double.go', 'constant.character.escape.go']); + } + + ({tokens} = grammar.tokenizeLine('"\\""')); + expect(tokens[1].value).toEqual('\\"'); + return expect(tokens[1].scopes).toEqual(['source.go', 'string.quoted.double.go', 'constant.character.escape.go']); +}); + + it('tokenizes placeholders in raw strings', function() { + // Taken from go/src/pkg/fmt/fmt_test.go + const verbs = [ + '%# x', '%-5s', '%5s', '%05s', '%.5s', '%10.1q', '%10v', '%-10v', '%.0d', + '%.d', '%+07.2f', '%0100d', '%0.100f', '%#064x', '%+.3F', '%-#20.8x', + '%[1]d', '%[2]*[1]d', '%[3]*.[2]*[1]f', '%[3]*.[2]f', '%3.[2]d', '%.[2]d', + '%-+[1]x', '%d', '%-d', '%+d', '%#d', '% d', '%0d', '%1.2d', '%-1.2d', + '%+1.2d', '%-+1.2d', '%*d', '%.*d', '%*.*d', '%0*d', '%-*d' + ]; + + return (() => { + const result = []; + for (let verb of Array.from(verbs)) { + const {tokens} = grammar.tokenizeLine('`' + verb + '`'); + expect(tokens[0].value).toEqual('`', + expect(tokens[0].scopes).toEqual(['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.begin.go'])); + expect(tokens[1].value).toEqual(verb); + expect(tokens[1].scopes).toEqual(['source.go', 'string.quoted.raw.go', 'constant.other.placeholder.go']); + result.push(expect(tokens[2].value).toEqual('`', + expect(tokens[2].scopes).toEqual(['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.end.go']))); + } + return result; + })(); +}); + + it('tokenizes runes', function() { + const runes = [ + 'u', 'X', '$', ':', '(', '.', '2', '=', '!', '@', + '\\a', '\\b', '\\f', '\\n', '\\r', '\\t', '\\v', '\\\\', "\\'", '\\"', + '\\000', '\\007', '\\377', '\\x07', '\\xff', '\\u12e4', '\\U00101234' + ]; + + return (() => { + const result = []; + for (let rune of Array.from(runes)) { + const {tokens} = grammar.tokenizeLine(`'${rune}'`); + expect(tokens[0]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go']}); + expect(tokens[1]).toEqual({value: rune, scopes: ['source.go', 'string.quoted.rune.go', 'constant.other.rune.go']}); + result.push(expect(tokens[2]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go']})); + } + return result; + })(); +}); + + it('tokenizes invalid runes and single quoted strings', function() { + let {tokens} = grammar.tokenizeLine("'\\c'"); + expect(tokens[0]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go']}); + expect(tokens[1]).toEqual({value: '\\c', scopes: ['source.go', 'string.quoted.rune.go', 'invalid.illegal.unknown-rune.go']}); + expect(tokens[2]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go']}); + + ({tokens} = grammar.tokenizeLine("'ab'")); + expect(tokens[0]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go']}); + expect(tokens[1]).toEqual({value: 'ab', scopes: ['source.go', 'string.quoted.rune.go', 'invalid.illegal.unknown-rune.go']}); + expect(tokens[2]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go']}); + + ({tokens} = grammar.tokenizeLine("'some single quote string'")); + expect(tokens[0]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go']}); + expect(tokens[1]).toEqual({value: 'some single quote string', scopes: ['source.go', 'string.quoted.rune.go', 'invalid.illegal.unknown-rune.go']}); + return expect(tokens[2]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go']}); +}); + + it('tokenizes invalid whitespace around chan annotations', function() { + let expr, invalid, tokens; + const invalid_send = + {'chan <- sendonly': ' '}; + + const invalid_receive = + {'<- chan recvonly': ' '}; + + for (expr in invalid_send) { + invalid = invalid_send[expr]; + ({tokens} = grammar.tokenizeLine(expr)); + expect(tokens[1].value).toEqual(invalid); + expect(tokens[1].scopes).toEqual(['source.go', 'invalid.illegal.send-channel.go']); + } + + return (() => { + const result = []; + for (expr in invalid_receive) { + invalid = invalid_receive[expr]; + ({tokens} = grammar.tokenizeLine(expr)); + expect(tokens[1].value).toEqual(invalid); + result.push(expect(tokens[1].scopes).toEqual(['source.go', 'invalid.illegal.receive-channel.go'])); + } + return result; + })(); +}); + + it('tokenizes keywords', function() { + const keywordLists = { + 'keyword.control.go': ['break', 'case', 'continue', 'default', 'defer', 'else', 'fallthrough', 'for', 'go', 'goto', 'if', 'range', 'return', 'select', 'switch'], + 'keyword.channel.go': ['chan'], + 'keyword.const.go': ['const'], + 'keyword.function.go': ['func'], + 'keyword.interface.go': ['interface'], + 'keyword.import.go': ['import'], + 'keyword.map.go': ['map'], + 'keyword.package.go': ['package'], + 'keyword.struct.go': ['struct'], + 'keyword.type.go': ['type'], + 'keyword.var.go': ['var'] + }; + + return (() => { + const result = []; + for (var scope in keywordLists) { + var list = keywordLists[scope]; + result.push((() => { + const result1 = []; + for (let keyword of Array.from(list)) { + const {tokens} = grammar.tokenizeLine(keyword); + expect(tokens[0].value).toEqual(keyword); + result1.push(expect(tokens[0].scopes).toEqual(['source.go', scope])); + } + return result1; + })()); + } + return result; + })(); +}); + + it('tokenizes storage types', function() { + const storageTypes = { + 'storage.type.boolean.go': ['bool'], + 'storage.type.byte.go': ['byte'], + 'storage.type.error.go': ['error'], + 'storage.type.numeric.go': ['int', 'int8', 'int16', 'int32', 'int64', 'uint', 'uint8', 'uint16', 'uint32', 'uint64', 'float32', 'float64', 'complex64', 'complex128'], + 'storage.type.rune.go': ['rune'], + 'storage.type.string.go': ['string'], + 'storage.type.uintptr.go': ['uintptr'] + }; + + return (() => { + const result = []; + for (var scope in storageTypes) { + var types = storageTypes[scope]; + result.push((() => { + const result1 = []; + for (let type of Array.from(types)) { + const {tokens} = grammar.tokenizeLine(type); + expect(tokens[0].value).toEqual(type); + result1.push(expect(tokens[0].scopes).toEqual(['source.go', scope])); + } + return result1; + })()); + } + return result; + })(); +}); + + it('tokenizes func regardless of the context', function() { + let line, tokens; + const funcKeyword = ['func f()', 'func (x) f()', 'func(x) f()', 'func']; + for (line of Array.from(funcKeyword)) { + ({tokens} = grammar.tokenizeLine(line)); + expect(tokens[0].value).toEqual('func'); + expect(tokens[0].scopes).toEqual(['source.go', 'keyword.function.go']); + } + + const funcType = [ + { + 'line': 'var f1 func(', + 'tokenPos': 4 + }, + { + 'line': 'f2 :=func()', + 'tokenPos': 3 + }, + { + 'line': '\tfunc(', + 'tokenPos': 1 + }, + { + 'line': 'type HandlerFunc func(', + 'tokenPos': 4 + } + ]; + return (() => { + const result = []; + for (let t of Array.from(funcType)) { + ({tokens} = grammar.tokenizeLine(t.line)); + const relevantToken = tokens[t.tokenPos]; + expect(relevantToken.value).toEqual('func'); + expect(relevantToken.scopes).toEqual(['source.go', 'keyword.function.go']); + + const next = tokens[t.tokenPos + 1]; + expect(next.value).toEqual('('); + result.push(expect(next.scopes).toEqual(['source.go', 'punctuation.definition.begin.bracket.round.go'])); + } + return result; + })(); +}); + + it('only tokenizes func when it is an exact match', function() { + const tests = ['myfunc', 'funcMap']; + return (() => { + const result = []; + for (let test of Array.from(tests)) { + const {tokens} = grammar.tokenizeLine(test); + expect(tokens[0].value).not.toEqual('func'); + result.push(expect(tokens[0].scopes).not.toEqual(['source.go', 'keyword.function.go'])); + } + return result; + })(); +}); + + it('tokenizes func names in their declarations', function() { + const tests = [ + { + 'line': 'func f()', + 'tokenPos': 2 + }, + { + 'line': 'func (T) f()', + 'tokenPos': 6 + }, + { + 'line': 'func (t T) f()', + 'tokenPos': 6 + }, + { + 'line': 'func (t *T) f()', + 'tokenPos': 8 + } + ]; + + return (() => { + const result = []; + for (let t of Array.from(tests)) { + const {tokens} = grammar.tokenizeLine(t.line); + expect(tokens[0].value).toEqual('func'); + expect(tokens[0].scopes).toEqual(['source.go', 'keyword.function.go']); + + const relevantToken = tokens[t.tokenPos]; + expect(relevantToken).toBeDefined(); + expect(relevantToken.value).toEqual('f'); + expect(relevantToken.scopes).toEqual(['source.go', 'entity.name.function.go']); + + const next = tokens[t.tokenPos + 1]; + expect(next.value).toEqual('('); + result.push(expect(next.scopes).toEqual(['source.go', 'punctuation.definition.begin.bracket.round.go'])); + } + return result; + })(); +}); + + it('tokenizes operators method declarations', function() { + const tests = [ + { + 'line': 'func (t *T) f()', + 'tokenPos': 4 + } + ]; + + return (() => { + const result = []; + for (let t of Array.from(tests)) { + const {tokens} = grammar.tokenizeLine(t.line); + expect(tokens[0].value).toEqual('func'); + expect(tokens[0].scopes).toEqual(['source.go', 'keyword.function.go']); + + const relevantToken = tokens[t.tokenPos]; + expect(relevantToken.value).toEqual('*'); + result.push(expect(relevantToken.scopes).toEqual(['source.go', 'keyword.operator.address.go'])); + } + return result; + })(); +}); + + it('tokenizes numerics', function() { + let num, tokens; + const numbers = { + 'constant.numeric.integer.go': ['42', '0600', '0xBadFace', '170141183460469231731687303715884105727', '1E6', '0i', '011i', '1E6i'], + 'constant.numeric.floating-point.go': [ + '0.', '72.40', '072.40', '2.71828', '1.e+0', '6.67428e-11', '.25', '.12345E+5', + '0.i', '2.71828i', '1.e+0i', '6.67428e-11i', '.25i', '.12345E+5i' + ] + }; + + for (let scope in numbers) { + const nums = numbers[scope]; + for (num of Array.from(nums)) { + ({tokens} = grammar.tokenizeLine(num)); + expect(tokens[0].value).toEqual(num); + expect(tokens[0].scopes).toEqual(['source.go', scope]); + } + } + + const invalidOctals = ['08', '039', '0995']; + return (() => { + const result = []; + for (num of Array.from(invalidOctals)) { + ({tokens} = grammar.tokenizeLine(num)); + expect(tokens[0].value).toEqual(num); + result.push(expect(tokens[0].scopes).toEqual(['source.go', 'invalid.illegal.numeric.go'])); + } + return result; + })(); +}); + + it('tokenizes language constants', function() { + const constants = ['true', 'false', 'nil', 'iota']; + return (() => { + const result = []; + for (let constant of Array.from(constants)) { + const {tokens} = grammar.tokenizeLine(constant); + expect(tokens[0].value).toEqual(constant); + result.push(expect(tokens[0].scopes).toEqual(['source.go', 'constant.language.go'])); + } + return result; + })(); +}); + + it('tokenizes built-in functions', function() { + const funcs = [ + 'append(x)', 'cap(x)', 'close(x)', 'complex(x)', 'copy(x)', 'delete(x)', 'imag(x)', 'len(x)', 'make(x)', 'new(x)', + 'panic(x)', 'print(x)', 'println(x)', 'real(x)', 'recover(x)' + ]; + const funcVals = ['append', 'cap', 'close', 'complex', 'copy', 'delete', 'imag', 'len', 'make', 'new', 'panic', 'print', 'println', 'real', 'recover']; + + return (() => { + const result = []; + for (let func of Array.from(funcs)) { + const funcVal = funcVals[funcs.indexOf(func)]; + const {tokens} = grammar.tokenizeLine(func); + expect(tokens[0].value).toEqual(funcVal); + result.push(expect(tokens[0].scopes).toEqual(['source.go', 'support.function.builtin.go'])); + } + return result; + })(); +}); + + it('tokenizes operators', function() { + let op, ops, scope, tokens; + const binaryOpers = { + 'keyword.operator.arithmetic.go': ['+', '-', '*', '/', '%'], + 'keyword.operator.arithmetic.bitwise.go': ['&', '|', '^', '&^', '<<', '>>'], + 'keyword.operator.assignment.go': ['=', '+=', '-=', '|=', '^=', '*=', '/=', ':=', '%=', '<<=', '>>=', '&=', '&^='], + 'keyword.operator.channel.go': ['<-'], + 'keyword.operator.comparison.go': ['==', '!=', '<', '<=', '>', '>='], + 'keyword.operator.decrement.go': ['--'], + 'keyword.operator.ellipsis.go': ['...'], + 'keyword.operator.increment.go': ['++'], + 'keyword.operator.logical.go': ['&&', '||'] + }; + + const unaryOpers = { + 'keyword.operator.address.go': ['*var', '&var'], + 'keyword.operator.arithmetic.go': ['+var', '-var'], + 'keyword.operator.arithmetic.bitwise.go': ['^var'], + 'keyword.operator.logical.go': ['!var'] + }; + + for (scope in binaryOpers) { + ops = binaryOpers[scope]; + for (op of Array.from(ops)) { + ({tokens} = grammar.tokenizeLine(op)); + expect(tokens[0].value).toEqual(op); + expect(tokens[0].scopes).toEqual(['source.go', scope]); + } + } + + return (() => { + const result = []; + for (scope in unaryOpers) { + ops = unaryOpers[scope]; + result.push((() => { + const result1 = []; + for (op of Array.from(ops)) { + ({tokens} = grammar.tokenizeLine(op)); + expect(tokens[0].value).toEqual(op[0]); + result1.push(expect(tokens[0].scopes).toEqual(['source.go', scope])); + } + return result1; + })()); + } + return result; + })(); +}); + + it('does not treat values/variables attached to comparion operators as extensions of the operator', function() { + const {tokens} = grammar.tokenizeLine('2<3.0 && 12>bar'); + expect(tokens[0]).toEqual({value: '2', scopes: ['source.go', 'constant.numeric.integer.go']}); + expect(tokens[1]).toEqual({value: '<', scopes: ['source.go', 'keyword.operator.comparison.go']}); + expect(tokens[2]).toEqual({value: '3.0', scopes: ['source.go', 'constant.numeric.floating-point.go']}); + expect(tokens[6]).toEqual({value: '12', scopes: ['source.go', 'constant.numeric.integer.go']}); + expect(tokens[7]).toEqual({value: '>', scopes: ['source.go', 'keyword.operator.comparison.go']}); + return expect(tokens[8]).toEqual({value: 'bar', scopes: ['source.go']}); +}); + + it('tokenizes punctuation brackets', function() { + const {tokens} = grammar.tokenizeLine('{([])}'); + expect(tokens[0]).toEqual({value: '{', scopes: ['source.go', 'punctuation.definition.begin.bracket.curly.go']}); + expect(tokens[1]).toEqual({value: '(', scopes: ['source.go', 'punctuation.definition.begin.bracket.round.go']}); + expect(tokens[2]).toEqual({value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + expect(tokens[3]).toEqual({value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + expect(tokens[4]).toEqual({value: ')', scopes: ['source.go', 'punctuation.definition.end.bracket.round.go']}); + return expect(tokens[5]).toEqual({value: '}', scopes: ['source.go', 'punctuation.definition.end.bracket.curly.go']}); +}); + + it('tokenizes punctuation delimiters', function() { + const delims = { + 'punctuation.other.comma.go': ',', + 'punctuation.other.period.go': '.', + 'punctuation.other.colon.go': ':' + }; + + return (() => { + const result = []; + for (let scope in delims) { + const delim = delims[scope]; + const {tokens} = grammar.tokenizeLine(delim); + expect(tokens[0].value).toEqual(delim); + result.push(expect(tokens[0].scopes).toEqual(['source.go', scope])); + } + return result; + })(); +}); + + it('tokenizes func names in calls to them', function() { + const tests = [ + { + 'line': 'a.b()', + 'name': 'b', + 'tokenPos': 2, + 'isFunc': true + }, + { + 'line': 'pkg.Func1(', + 'name': 'Func1', + 'tokenPos': 2, + 'isFunc': true + }, + { + 'line': 'pkg.Func1().Func2(', + 'name': 'Func2', + 'tokenPos': 6, + 'isFunc': true + }, + { + 'line': 'pkg.var', + 'name': 'var', + 'tokenPos': 2, + 'isFunc': false + }, + { + 'line': 'doWork(ch)', + 'name': 'doWork', + 'tokenPos': 0, + 'isFunc': true + }, + { + 'line': 'f1()', + 'name': 'f1', + 'tokenPos': 0, + 'isFunc': true + } + ]; + + const want = ['source.go', 'support.function.go']; + + return (() => { + const result = []; + for (let t of Array.from(tests)) { + const {tokens} = grammar.tokenizeLine(t.line); + + const relevantToken = tokens[t.tokenPos]; + if (t.isFunc) { + expect(relevantToken).not.toBeNull(); + expect(relevantToken.value).toEqual(t.name); + expect(relevantToken.scopes).toEqual(want); + + const next = tokens[t.tokenPos + 1]; + expect(next.value).toEqual('('); + result.push(expect(next.scopes).toEqual(['source.go', 'punctuation.definition.begin.bracket.round.go'])); + } else { + result.push(expect(relevantToken.scopes).not.toEqual(want)); + } + } + return result; + })(); + }); + + it('tokenizes package names', function() { + const tests = ['package main', 'package mypackage']; + + return (() => { + const result = []; + for (let test of Array.from(tests)) { + const {tokens} = grammar.tokenizeLine(test); + expect(tokens[0].scopes).toEqual(['source.go', 'keyword.package.go']); + result.push(expect(tokens[2].scopes).toEqual(['source.go', 'entity.name.package.go'])); + } + return result; + })(); +}); + + it('tokenizes invalid package names as such', function() { + const {tokens} = grammar.tokenizeLine('package 0mypackage'); + expect(tokens[0]).toEqual({value: 'package', scopes: ['source.go', 'keyword.package.go']}); + return expect(tokens[2]).toEqual({value: '0mypackage', scopes: ['source.go', 'invalid.illegal.identifier.go']}); +}); + + it('does not treat words that have a trailing package as a package name', function() { + const {tokens} = grammar.tokenizeLine('func myFunc(Varpackage string)'); + expect(tokens[4]).toEqual({value: 'Varpackage ', scopes: ['source.go']}); + return expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); +}); + + it('tokenizes type names', function() { + const tests = ['type mystring string', 'type mytype interface{']; + + return (() => { + const result = []; + for (let test of Array.from(tests)) { + const {tokens} = grammar.tokenizeLine(test); + expect(tokens[0].scopes).toEqual(['source.go', 'keyword.type.go']); + result.push(expect(tokens[2].scopes).toEqual(['source.go', 'entity.name.type.go'])); + } + return result; + })(); +}); + + it('tokenizes invalid type names as such', function() { + const {tokens} = grammar.tokenizeLine('type 0mystring string'); + expect(tokens[0]).toEqual({value: 'type', scopes: ['source.go', 'keyword.type.go']}); + return expect(tokens[2]).toEqual({value: '0mystring', scopes: ['source.go', 'invalid.illegal.identifier.go']}); +}); + + it('does not treat words that have a trailing type as a type name', function() { + const {tokens} = grammar.tokenizeLine('func myFunc(Vartype string)'); + expect(tokens[4]).toEqual({value: 'Vartype ', scopes: ['source.go']}); + return expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); +}); + + describe('in variable declarations', function() { + const testVar = function(token) { + expect(token.value).toBe('var'); + return expect(token.scopes).toEqual(['source.go', 'keyword.var.go']); + }; + + const testVarAssignment = function(token, name) { + expect(token.value).toBe(name); + return expect(token.scopes).toEqual(['source.go', 'variable.other.assignment.go']); + }; + + const testVarDeclaration = function(token, name) { + expect(token.value).toBe(name); + return expect(token.scopes).toEqual(['source.go', 'variable.other.declaration.go']); + }; + + const testOp = function(token, op) { + expect(token.value).toBe(op); + return expect(token.scopes).toEqual(['source.go', 'keyword.operator.go']); + }; + + const testOpAddress = function(token, op) { + expect(token.value).toBe(op); + return expect(token.scopes).toEqual(['source.go', 'keyword.operator.address.go']); + }; + + const testOpAssignment = function(token, op) { + expect(token.value).toBe(op); + return expect(token.scopes).toEqual(['source.go', 'keyword.operator.assignment.go']); + }; + + const testOpBracket = function(token, op, type) { + expect(token.value).toBe(op); + return expect(token.scopes).toEqual(['source.go', `punctuation.definition.variables.${type}.bracket.round.go`]); + }; + + const testOpPunctuation = function(token, op) { + expect(token.value).toBe(op); + return expect(token.scopes).toEqual(['source.go', 'punctuation.other.comma.go']); + }; + + const testOpTermination = function(token, op) { + expect(token.value).toBe(op); + return expect(token.scopes).toEqual(['source.go', 'punctuation.terminator.go']); + }; + + const testNumType = function(token, name) { + expect(token.value).toBe(name); + return expect(token.scopes).toEqual(['source.go', 'storage.type.numeric.go']); + }; + + const testStringType = function(token, name) { + expect(token.value).toBe(name); + return expect(token.scopes).toEqual(['source.go', 'storage.type.string.go']); + }; + + const testNum = function(token, value) { + expect(token.value).toBe(value); + return expect(token.scopes).toEqual(['source.go', 'constant.numeric.integer.go']); + }; + + const testString = function(token, value) { + expect(token.value).toBe(value); + return expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go']); + }; + + return describe('in var statements', function() { + it('tokenizes a single variable assignment', function() { + const {tokens} = grammar.tokenizeLine('i = 7'); + testVarAssignment(tokens[0], 'i'); + testOpAssignment(tokens[2], '='); + return testNum(tokens[4], '7'); + }); + + it('tokenizes a single qualified variable assignment', function() { + const {tokens} = grammar.tokenizeLine('a.b.cde = 7'); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.go', 'variable.other.assignment.go']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.go', 'variable.other.assignment.go']}); + expect(tokens[3]).toEqual({value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go']}); + expect(tokens[4]).toEqual({value: 'cde', scopes: ['source.go', 'variable.other.assignment.go']}); + testOpAssignment(tokens[6], '='); + return testNum(tokens[8], '7'); + }); + + it('tokenizes multiple variable assignments', function() { + const {tokens} = grammar.tokenizeLine('i, j = 7, 8'); + testVarAssignment(tokens[0], 'i'); + testOpPunctuation(tokens[1], ','); + testVarAssignment(tokens[3], 'j'); + testOpAssignment(tokens[5], '='); + testNum(tokens[7], '7'); + return testNum(tokens[10], '8'); + }); + + it('tokenizes multiple qualified variable assignment', function() { + const {tokens} = grammar.tokenizeLine('a.b, c.d.efg = 7, 8'); + expect(tokens[0]).toEqual({value: 'a', scopes: ['source.go', 'variable.other.assignment.go']}); + expect(tokens[1]).toEqual({value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go']}); + expect(tokens[2]).toEqual({value: 'b', scopes: ['source.go', 'variable.other.assignment.go']}); + testOpPunctuation(tokens[3], ','); + expect(tokens[5]).toEqual({value: 'c', scopes: ['source.go', 'variable.other.assignment.go']}); + expect(tokens[6]).toEqual({value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go']}); + expect(tokens[7]).toEqual({value: 'd', scopes: ['source.go', 'variable.other.assignment.go']}); + expect(tokens[8]).toEqual({value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go']}); + expect(tokens[9]).toEqual({value: 'efg', scopes: ['source.go', 'variable.other.assignment.go']}); + testOpAssignment(tokens[11], '='); + testNum(tokens[13], '7'); + return testNum(tokens[16], '8'); + }); + + it('tokenizes a single name and a type', function() { + const {tokens} = grammar.tokenizeLine('var i int'); + testVar(tokens[0]); + testVarDeclaration(tokens[2], 'i'); + return testNumType(tokens[4], 'int'); + }); + + it('tokenizes a name and a qualified type', function() { + const {tokens} = grammar.tokenizeLine('var a b.c'); + testVar(tokens[0]); + expect(tokens[2]).toEqual({value: 'a', scopes: ['source.go', 'variable.other.declaration.go']}); + expect(tokens[3]).toEqual({value: ' b', scopes: ['source.go']}); + expect(tokens[4]).toEqual({value: '.', scopes: ['source.go', 'punctuation.other.period.go']}); + return expect(tokens[5]).toEqual({value: 'c', scopes: ['source.go']}); + }); + + it('tokenizes a single name and an array type', function() { + const {tokens} = grammar.tokenizeLine('var s []string'); + testVar(tokens[0]); + testVarDeclaration(tokens[2], 's'); + return testStringType(tokens[6], 'string'); + }); + + it('tokenizes a single name and an array type with predetermined length', function() { + const {tokens} = grammar.tokenizeLine('var s [4]string'); + testVar(tokens[0]); + testVarDeclaration(tokens[2], 's'); + expect(tokens[4]).toEqual({value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + expect(tokens[5]).toEqual({value: '4', scopes: ['source.go', 'constant.numeric.integer.go']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + return testStringType(tokens[7], 'string'); + }); + + it('tokenizes a single name and an array type with variadic length', function() { + const {tokens} = grammar.tokenizeLine('var s [...]string'); + testVar(tokens[0]); + testVarDeclaration(tokens[2], 's'); + expect(tokens[4]).toEqual({value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + expect(tokens[5]).toEqual({value: '...', scopes: ['source.go', 'keyword.operator.ellipsis.go']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + return testStringType(tokens[7], 'string'); + }); + + it('tokenizes a single name and multi-dimensional types with an address', function() { + const {tokens} = grammar.tokenizeLine('var e [][]*string'); + testVar(tokens[0]); + testVarDeclaration(tokens[2], 'e'); + expect(tokens[4]).toEqual({value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + expect(tokens[5]).toEqual({value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + expect(tokens[6]).toEqual({value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + expect(tokens[7]).toEqual({value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); + testOpAddress(tokens[8], '*'); + return testStringType(tokens[9], 'string'); + }); + + it('tokenizes a single name and a channel', function() { + const {tokens} = grammar.tokenizeLine('var x <-chan bool'); + testVar(tokens[0]); + testVarDeclaration(tokens[2], 'x'); + expect(tokens[4]).toEqual({value: '<-', scopes: ['source.go', 'keyword.operator.channel.go']}); + expect(tokens[5]).toEqual({value: 'chan', scopes: ['source.go', 'keyword.channel.go']}); + return expect(tokens[7]).toEqual({value: 'bool', scopes: ['source.go', 'storage.type.boolean.go']}); + }); + + it('tokenizes a single name and its initialization', function() { + const {tokens} = grammar.tokenizeLine(' var k = 0'); + testVar(tokens[1]); + testVarAssignment(tokens[3], 'k'); + testOpAssignment(tokens[5], '='); + return testNum(tokens[7], '0'); + }); + + it('tokenizes a single name, a type, and an initialization', function() { + const {tokens} = grammar.tokenizeLine('var z blub = 7'); + testVar(tokens[0]); + testVarAssignment(tokens[2], 'z'); + expect(tokens[3]).toEqual({value: ' blub ', scopes: ['source.go']}); + testOpAssignment(tokens[4], '='); + return testNum(tokens[6], '7'); + }); + + it('tokenizes a single name, a qualified type, and an initialization', function() { + const {tokens} = grammar.tokenizeLine('var a b.c = 5'); + testVar(tokens[0]); + expect(tokens[2]).toEqual({value: 'a', scopes: ['source.go', 'variable.other.assignment.go']}); + expect(tokens[3]).toEqual({value: ' b', scopes: ['source.go']}); + expect(tokens[4]).toEqual({value: '.', scopes: ['source.go', 'punctuation.other.period.go']}); + expect(tokens[5]).toEqual({value: 'c ', scopes: ['source.go']}); + testOpAssignment(tokens[6], '='); + return testNum(tokens[8], '5'); + }); + + it('does not tokenize more than necessary', function() { + // This test is worded vaguely because it's hard to describe. + // Basically, make sure that the variable match isn't tokenizing the entire line + // in a (=.+) style match. This prevents multiline stuff after the assignment + // from working correctly, because match can only tokenize single lines. + const lines = grammar.tokenizeLines(`\ +var multiline string = \`wow! +this should work!\`\ +` + ); + testVar(lines[0][0]); + testVarAssignment(lines[0][2], 'multiline'); + testStringType(lines[0][4], 'string'); + testOpAssignment(lines[0][6], '='); + expect(lines[0][8]).toEqual({value: '`', scopes: ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.begin.go']}); + return expect(lines[1][1]).toEqual({value: '`', scopes: ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.end.go']}); + }); + + it('tokenizes multiple names and a type', function() { + const {tokens} = grammar.tokenizeLine('var U, V, W float64'); + testVar(tokens[0]); + testVarDeclaration(tokens[2], 'U'); + testOpPunctuation(tokens[3], ','); + testVarDeclaration(tokens[5], 'V'); + testOpPunctuation(tokens[6], ','); + return testVarDeclaration(tokens[8], 'W'); + }); + + it('tokenizes multiple names and a qualified type', function() { + const {tokens} = grammar.tokenizeLine('var a, b c.d'); + testVar(tokens[0]); + expect(tokens[2]).toEqual({value: 'a', scopes: ['source.go', 'variable.other.declaration.go']}); + testOpPunctuation(tokens[3], ','); + expect(tokens[5]).toEqual({value: 'b', scopes: ['source.go', 'variable.other.declaration.go']}); + expect(tokens[6]).toEqual({value: ' c', scopes: ['source.go']}); + expect(tokens[7]).toEqual({value: '.', scopes: ['source.go', 'punctuation.other.period.go']}); + return expect(tokens[8]).toEqual({value: 'd', scopes: ['source.go']}); + }); + + it('tokenizes multiple names and initialization expressions', function() { + const {tokens} = grammar.tokenizeLine('var x, y, z = 1, 2, 3'); + testVar(tokens[0]); + testVarAssignment(tokens[2], 'x'); + testOpPunctuation(tokens[3], ','); + testVarAssignment(tokens[5], 'y'); + testOpPunctuation(tokens[6], ','); + testVarAssignment(tokens[8], 'z'); + testOpAssignment(tokens[10], '='); + testNum(tokens[12], '1'); + testOpPunctuation(tokens[13], ','); + testNum(tokens[15], '2'); + testOpPunctuation(tokens[16], ','); + return testNum(tokens[18], '3'); + }); + + it('tokenizes multiple names, a type, and initialization expressions', function() { + const {tokens} = grammar.tokenizeLine('var x, y float32 = float, thirtytwo'); + testVar(tokens[0]); + testVarAssignment(tokens[2], 'x'); + testOpPunctuation(tokens[3], ','); + testVarAssignment(tokens[5], 'y'); + testNumType(tokens[7], 'float32'); + testOpAssignment(tokens[9], '='); + return testOpPunctuation(tokens[11], ','); + }); + + it('tokenizes multiple names, a qualified type, and initialization expression', function() { + const {tokens} = grammar.tokenizeLine('var a, b c.d = 1, 2'); + testVar(tokens[0]); + expect(tokens[2]).toEqual({value: 'a', scopes: ['source.go', 'variable.other.assignment.go']}); + testOpPunctuation(tokens[3], ','); + expect(tokens[5]).toEqual({value: 'b', scopes: ['source.go', 'variable.other.assignment.go']}); + expect(tokens[6]).toEqual({value: ' c', scopes: ['source.go']}); + expect(tokens[7]).toEqual({value: '.', scopes: ['source.go', 'punctuation.other.period.go']}); + expect(tokens[8]).toEqual({value: 'd ', scopes: ['source.go']}); + testOpAssignment(tokens[9], '='); + testNum(tokens[11], '1'); + testOpPunctuation(tokens[12], ','); + return testNum(tokens[14], '2'); + }); + + it('tokenizes multiple names and a function call', function() { + const {tokens} = grammar.tokenizeLine('var re, im = complexSqrt(-1)'); + testVar(tokens[0]); + testVarAssignment(tokens[2], 're'); + testVarAssignment(tokens[5], 'im'); + return testOpAssignment(tokens[7], '='); + }); + + it('tokenizes with a placeholder', function() { + const {tokens} = grammar.tokenizeLine('var _, found = entries[name]'); + testVar(tokens[0]); + testVarAssignment(tokens[2], '_'); + testVarAssignment(tokens[5], 'found'); + return testOpAssignment(tokens[7], '='); + }); + + it('does not treat words that have a trailing var as a variable declaration', function() { + const {tokens} = grammar.tokenizeLine('func test(envvar string)'); + expect(tokens[4]).toEqual({value: 'envvar ', scopes: ['source.go']}); + return expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); + }); + + describe('in var statement blocks', function() { + it('tokenizes single names with a type', function() { + const lines = grammar.tokenizeLines(`\ +var ( + foo *bar +)\ +` + ); + testVar(lines[0][0]); + testOpBracket(lines[0][2], '(', 'begin'); + testVarDeclaration(lines[1][1], 'foo'); + testOpAddress(lines[1][3], '*'); + return testOpBracket(lines[2][0], ')', 'end'); + }); + + it('tokenizes single names with an initializer', function() { + const lines = grammar.tokenizeLines(`\ +var ( + foo = 42 +)\ +` + ); + testVar(lines[0][0], 'var'); + testOpBracket(lines[0][2], '(', 'begin'); + testVarAssignment(lines[1][1], 'foo'); + testOpAssignment(lines[1][3], '='); + testNum(lines[1][5], '42'); + return testOpBracket(lines[2][0], ')', 'end'); + }); + + it('tokenizes multiple names', function() { + const lines = grammar.tokenizeLines(`\ +var ( + foo, bar = baz, quux +)\ +` + ); + testVar(lines[0][0]); + testOpBracket(lines[0][2], '(', 'begin'); + testVarAssignment(lines[1][1], 'foo'); + testOpPunctuation(lines[1][2], ','); + testVarAssignment(lines[1][4], 'bar'); + testOpAssignment(lines[1][6], '='); + testOpPunctuation(lines[1][8], ','); + return testOpBracket(lines[2][0], ')', 'end'); + }); + + it('tokenizes non variable declarations', function() { + const lines = grammar.tokenizeLines(`\ +var ( + // I am a comment + foo *bar + userRegister = &routers.Handler{ + Handler: func(c echo.Context) error { + if err := userService.Register(&user); err != nil { + return err + } + return nil + }, + } +)\ +` + ); + testVar(lines[0][0]); + testOpBracket(lines[0][2], '(', 'begin'); + expect(lines[1][1]).toEqual({value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']}); + expect(lines[1][2]).toEqual({value: ' I am a comment', scopes: ['source.go', 'comment.line.double-slash.go']}); + testVarDeclaration(lines[2][1], 'foo'); + testOpAddress(lines[2][3], '*'); + testVarAssignment(lines[3][1], 'userRegister'); + expect(lines[4][3]).toEqual({value: 'func', scopes: ['source.go', 'keyword.function.go']}); + expect(lines[5][1]).toEqual({value: 'if', scopes: ['source.go', 'keyword.control.go']}); + expect(lines[8][3]).toEqual({value: 'nil', scopes: ['source.go', 'constant.language.go']}); + return testOpBracket(lines[11][0], ')', 'end'); + }); + + return it('tokenizes all parts of variable initializations correctly', function() { + const lines = grammar.tokenizeLines(`\ +var ( + m = map[string]int{ + "key": 10, + } +)\ +` + ); + testVar(lines[0][0]); + testOpBracket(lines[0][2], '(', 'begin'); + testVarAssignment(lines[1][1], 'm'); + testOpAssignment(lines[1][3], '='); + testString(lines[2][2], 'key'); + testNum(lines[2][6], '10'); + return testOpBracket(lines[4][0], ')', 'end'); + }); + }); + + it('tokenizes non-ASCII variable names', function() { + const {tokens} = grammar.tokenizeLine('über = test'); + testVarAssignment(tokens[0], 'über'); + return testOpAssignment(tokens[2], '='); + }); + + it('tokenizes invalid variable names as such', function() { + const {tokens} = grammar.tokenizeLine('var 0test = 0'); + testVar(tokens[0]); + return expect(tokens[2]).toEqual({value: '0test', scopes: ['source.go', 'invalid.illegal.identifier.go']}); + }); + + return describe('in shorthand variable declarations', function() { + it('tokenizes single names', function() { + let {tokens} = grammar.tokenizeLine('f := func() int { return 7 }'); + testVarAssignment(tokens[0], 'f'); + testOpAssignment(tokens[2], ':='); + + ({tokens} = grammar.tokenizeLine('ch := make(chan int)')); + testVarAssignment(tokens[0], 'ch'); + return testOpAssignment(tokens[2], ':='); + }); + + return it('tokenizes multiple names', function() { + let {tokens} = grammar.tokenizeLine('i, j := 0, 10'); + testVarAssignment(tokens[0], 'i'); + testOpPunctuation(tokens[1], ','); + testVarAssignment(tokens[3], 'j'); + + ({tokens} = grammar.tokenizeLine('if _, y, z := coord(p); z > 0')); + testVarAssignment(tokens[2], '_'); + testVarAssignment(tokens[5], 'y'); + testVarAssignment(tokens[8], 'z'); + testOpAssignment(tokens[10], ':='); + return testOpTermination(tokens[16], ';'); + }); + }); + }); + }); + + return describe('in imports declarations', function() { + const testImport = function(token) { + expect(token.value).toBe('import'); + return expect(token.scopes).toEqual(['source.go', 'keyword.import.go']); + }; + + const testImportAlias = function(token, name) { + expect(token.value).toBe(name); + return expect(token.scopes).toEqual(['source.go', 'entity.alias.import.go']); + }; + + const testImportPackage = function(token, name) { + expect(token.value).toBe(name); + return expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'entity.name.import.go']); + }; + + const testOpBracket = function(token, op, type) { + expect(token.value).toBe(op); + return expect(token.scopes).toEqual(['source.go', `punctuation.definition.imports.${type}.bracket.round.go`]); + }; + + const testBeginQuoted = function(token) { + expect(token.value).toBe('"'); + return expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'punctuation.definition.string.begin.go']); + }; + + const testEndQuoted = function(token) { + expect(token.value).toBe('"'); + return expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'punctuation.definition.string.end.go']); + }; + + describe('when it is a single line declaration', function() { + it('tokenizes declarations with a package name', function() { + const {tokens} = grammar.tokenizeLine('import "fmt"'); + testImport(tokens[0]); + testBeginQuoted(tokens[2]); + testImportPackage(tokens[3], 'fmt'); + return testEndQuoted(tokens[4]); + }); + + it('tokenizes declarations with a package name and an alias', function() { + let {tokens} = grammar.tokenizeLine('import . "fmt"'); + testImport(tokens[0]); + testImportAlias(tokens[2], '.'); + testBeginQuoted(tokens[4]); + testImportPackage(tokens[5], 'fmt'); + testEndQuoted(tokens[6]); + ({tokens} = grammar.tokenizeLine('import otherpackage "github.com/test/package"')); + testImport(tokens[0]); + testImportAlias(tokens[2], 'otherpackage'); + testBeginQuoted(tokens[4]); + testImportPackage(tokens[5], 'github.com/test/package'); + return testEndQuoted(tokens[6]); + }); + + return it('does not treat words that have a trailing import as a import declaration', function() { + const {tokens} = grammar.tokenizeLine('func myFunc(Varimport string)'); + expect(tokens[4]).toEqual({value: 'Varimport ', scopes: ['source.go']}); + return expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); + }); + }); + + return describe('when it is a multi line declaration', function() { + it('tokenizes single declarations with a package name', function() { + const [kwd, decl, closing] = Array.from(grammar.tokenizeLines(`\ +import ( + "github.com/test/package" +)\ +` + )); + testImport(kwd[0]); + testOpBracket(kwd[2], '(', 'begin'); + testBeginQuoted(decl[1]); + testImportPackage(decl[2], 'github.com/test/package'); + testEndQuoted(decl[3]); + return testOpBracket(closing[0], ')', 'end'); + }); + + it('tokenizes multiple declarations with a package name', function() { + const [kwd, decl, decl2, closing] = Array.from(grammar.tokenizeLines(`\ +import ( + "github.com/test/package" + "fmt" +)\ +` + )); + testImport(kwd[0]); + testOpBracket(kwd[2], '(', 'begin'); + testBeginQuoted(decl[1]); + testImportPackage(decl[2], 'github.com/test/package'); + testEndQuoted(decl[3]); + testBeginQuoted(decl2[1]); + testImportPackage(decl2[2], 'fmt'); + testEndQuoted(decl2[3]); + return testOpBracket(closing[0], ')', 'end'); + }); + + it('tokenizes single imports with an alias for a multi-line declaration', function() { + const [kwd, decl, closing] = Array.from(grammar.tokenizeLines(`\ +import ( + . "github.com/test/package" +)\ +` + )); + testImport(kwd[0]); + testOpBracket(kwd[2], '(', 'begin'); + testImportAlias(decl[1], '.'); + testBeginQuoted(decl[3]); + testImportPackage(decl[4], 'github.com/test/package'); + testEndQuoted(decl[5]); + return testOpBracket(closing[0], ')', 'end'); + }); + + return it('tokenizes multiple imports with an alias for a multi-line declaration', function() { + const [kwd, decl, decl2, closing] = Array.from(grammar.tokenizeLines(`\ +import ( + . "github.com/test/package" + "fmt" +)\ +` + )); + testImport(kwd[0]); + testOpBracket(kwd[2], '(', 'begin'); + testImportAlias(decl[1], '.'); + testBeginQuoted(decl[3]); + testImportPackage(decl[4], 'github.com/test/package'); + testEndQuoted(decl[5]); + testBeginQuoted(decl2[1]); + testImportPackage(decl2[2], 'fmt'); + testEndQuoted(decl2[3]); + return testOpBracket(closing[0], ')', 'end'); + }); + }); + }); +}); diff --git a/packages/language-go/spec/language-go-spec.js b/packages/language-go/spec/language-go-spec.js new file mode 100644 index 0000000000..5b5aff7dcc --- /dev/null +++ b/packages/language-go/spec/language-go-spec.js @@ -0,0 +1,72 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ +describe('Go settings', function() { + let [editor, languageMode] = Array.from([]); + + afterEach(() => editor.destroy()); + + beforeEach(function() { + atom.config.set('core.useTreeSitterParsers', false); + + + waitsForPromise(() => atom.workspace.open().then(function(o) { + editor = o; + return languageMode = editor.languageMode; + })); + + return waitsForPromise(() => atom.packages.activatePackage('language-go')); + }); + + it('matches lines correctly using the increaseIndentPattern', function() { + const increaseIndentRegex = languageMode.increaseIndentRegexForScopeDescriptor(['source.go']); + + expect(increaseIndentRegex.findNextMatchSync(' case true:')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' default:')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync('func something() {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' if true {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' else {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' switch {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' switch true {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' select {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' select true {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' for v := range val {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' for i := 0; i < 10; i++ {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' for i := 0; i < 10; i++ {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' type something struct {')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' fmt.Printf("some%s",')).toBeTruthy(); + return expect(increaseIndentRegex.findNextMatchSync(' aSlice := []string{}{')).toBeTruthy(); + }); + + it('matches lines correctly using the decreaseIndentPattern', function() { + const decreaseIndentRegex = languageMode.decreaseIndentRegexForScopeDescriptor(['source.go']); + + expect(decreaseIndentRegex.findNextMatchSync(' case true:')).toBeTruthy(); + expect(decreaseIndentRegex.findNextMatchSync(' default:')).toBeTruthy(); + expect(decreaseIndentRegex.findNextMatchSync(' }')).toBeTruthy(); + expect(decreaseIndentRegex.findNextMatchSync(' },')).toBeTruthy(); + expect(decreaseIndentRegex.findNextMatchSync(' )')).toBeTruthy(); + return expect(decreaseIndentRegex.findNextMatchSync(' ),')).toBeTruthy(); + }); + + return it('matches lines correctly using the decreaseNextIndentPattern', function() { + const decreaseNextIndentRegex = languageMode.decreaseNextIndentRegexForScopeDescriptor(['source.go']); + + expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something"))')).toBeTruthy(); + expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something")),')).toBeTruthy(); + expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something"), "x"),')).toBeTruthy(); + expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println(fmt.Sprint("something"))),')).toBeTruthy(); + expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println(fmt.Sprint("something"), "x")),')).toBeTruthy(); + + expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something")')).toBeFalsy(); + expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something"),')).toBeFalsy(); + + // a line with many (), testing for catastrophic backtracking. + // see https://github.com/atom/language-go/issues/78 + const longLine = 'first.second().third().fourth().fifth().sixth().seventh().eighth().ninth().tenth()'; + return expect(decreaseNextIndentRegex.findNextMatchSync(longLine)).toBeFalsy(); + }); +}); From 39e59555e6e0be117111dda090531e5cffbd576c Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 17:58:56 -0700 Subject: [PATCH 02/18] Manual decaf `language-c`; Remove CoffeeScript --- packages/language-c/spec/c-spec.coffee | 1140 ------------------------ packages/language-c/spec/c-spec.js | 146 +-- 2 files changed, 73 insertions(+), 1213 deletions(-) delete mode 100644 packages/language-c/spec/c-spec.coffee diff --git a/packages/language-c/spec/c-spec.coffee b/packages/language-c/spec/c-spec.coffee deleted file mode 100644 index 63da746928..0000000000 --- a/packages/language-c/spec/c-spec.coffee +++ /dev/null @@ -1,1140 +0,0 @@ -TextEditor = null -buildTextEditor = (params) -> - if atom.workspace.buildTextEditor? - atom.workspace.buildTextEditor(params) - else - TextEditor ?= require('atom').TextEditor - new TextEditor(params) - -describe "Language-C", -> - grammar = null - - beforeEach -> - atom.config.set 'core.useTreeSitterParsers', false - - waitsForPromise -> - atom.packages.activatePackage('language-c') - - describe "C", -> - beforeEach -> - grammar = atom.grammars.grammarForScopeName('source.c') - - it "parses the grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe 'source.c' - - it "tokenizes punctuation", -> - {tokens} = grammar.tokenizeLine 'hi;' - expect(tokens[1]).toEqual value: ';', scopes: ['source.c', 'punctuation.terminator.statement.c'] - - {tokens} = grammar.tokenizeLine 'a[b]' - expect(tokens[1]).toEqual value: '[', scopes: ['source.c', 'punctuation.definition.begin.bracket.square.c'] - expect(tokens[3]).toEqual value: ']', scopes: ['source.c', 'punctuation.definition.end.bracket.square.c'] - - {tokens} = grammar.tokenizeLine 'a, b' - expect(tokens[1]).toEqual value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c'] - - it "tokenizes functions", -> - lines = grammar.tokenizeLines ''' - int something(int param) { - return 0; - } - ''' - expect(lines[0][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] - expect(lines[0][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[0][3]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(lines[0][4]).toEqual value: 'int', scopes: ['source.c', 'meta.function.c', 'storage.type.c'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - expect(lines[0][8]).toEqual value: '{', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[1][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] - expect(lines[1][3]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] - expect(lines[2][0]).toEqual value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - it "tokenizes varargs ellipses", -> - {tokens} = grammar.tokenizeLine 'void function(...);' - expect(tokens[0]).toEqual value: 'void', scopes: ['source.c', 'storage.type.c'] - expect(tokens[2]).toEqual value: 'function', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(tokens[4]).toEqual value: '...', scopes: ['source.c', 'meta.function.c', 'punctuation.vararg-ellipses.c'] - expect(tokens[5]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - - it "tokenizes various _t types", -> - {tokens} = grammar.tokenizeLine 'size_t var;' - expect(tokens[0]).toEqual value: 'size_t', scopes: ['source.c', 'support.type.sys-types.c'] - - {tokens} = grammar.tokenizeLine 'pthread_t var;' - expect(tokens[0]).toEqual value: 'pthread_t', scopes: ['source.c', 'support.type.pthread.c'] - - {tokens} = grammar.tokenizeLine 'int32_t var;' - expect(tokens[0]).toEqual value: 'int32_t', scopes: ['source.c', 'support.type.stdint.c'] - - {tokens} = grammar.tokenizeLine 'myType_t var;' - expect(tokens[0]).toEqual value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c'] - - it "tokenizes 'line continuation' character", -> - {tokens} = grammar.tokenizeLine 'ma' + '\\' + '\n' + 'in(){};' - expect(tokens[0]).toEqual value: 'ma', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '\\', scopes: ['source.c', 'constant.character.escape.line-continuation.c'] - expect(tokens[3]).toEqual value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - - describe "strings", -> - it "tokenizes them", -> - delimsByScope = - 'string.quoted.double.c': '"' - 'string.quoted.single.c': '\'' - - for scope, delim of delimsByScope - {tokens} = grammar.tokenizeLine delim + 'a' + delim - expect(tokens[0]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.c', scope] - expect(tokens[2]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine delim + 'a' + '\\' + '\n' + 'b' + delim - expect(tokens[0]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.c', scope] - expect(tokens[2]).toEqual value: '\\', scopes: ['source.c', scope, 'constant.character.escape.line-continuation.c'] - expect(tokens[4]).toEqual value: 'b', scopes: ['source.c', scope] - expect(tokens[5]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '"%d"' - expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: '%d', scopes: ['source.c', 'string.quoted.double.c', 'constant.other.placeholder.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '"%"' - expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c', 'invalid.illegal.placeholder.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '"%" PRId32' - expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '"%" SCNd32' - expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - describe "comments", -> - it "tokenizes them", -> - {tokens} = grammar.tokenizeLine '/**/' - expect(tokens[0]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(tokens[1]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - - {tokens} = grammar.tokenizeLine '/* foo */' - expect(tokens[0]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(tokens[1]).toEqual value: ' foo ', scopes: ['source.c', 'comment.block.c'] - expect(tokens[2]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - - {tokens} = grammar.tokenizeLine '*/*' - expect(tokens[0]).toEqual value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c'] - - describe "preprocessor directives", -> - it "tokenizes '#line'", -> - {tokens} = grammar.tokenizeLine '#line 151 "copy.c"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.line.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'line', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.line.c'] - expect(tokens[3]).toEqual value: '151', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[6]).toEqual value: 'copy.c', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - it "tokenizes '#undef'", -> - {tokens} = grammar.tokenizeLine '#undef FOO' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'undef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] - expect(tokens[3]).toEqual value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - - it "tokenizes '#pragma'", -> - {tokens} = grammar.tokenizeLine '#pragma once' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'pragma', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.pragma.c'] - expect(tokens[3]).toEqual value: 'once', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] - - {tokens} = grammar.tokenizeLine '#pragma clang diagnostic ignored "-Wunused-variable"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'pragma', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.pragma.c'] - expect(tokens[3]).toEqual value: 'clang', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] - expect(tokens[5]).toEqual value: 'diagnostic', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] - expect(tokens[7]).toEqual value: 'ignored', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] - expect(tokens[10]).toEqual value: '-Wunused-variable', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'string.quoted.double.c'] - - {tokens} = grammar.tokenizeLine '#pragma mark – Initialization' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'pragma mark', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c'] - expect(tokens[3]).toEqual value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c'] - - describe "define", -> - it "tokenizes '#define [identifier name]'", -> - {tokens} = grammar.tokenizeLine '#define _FILE_NAME_H_' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - - it "tokenizes '#define [identifier name] [value]'", -> - {tokens} = grammar.tokenizeLine '#define WIDTH 80' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'WIDTH', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[5]).toEqual value: '80', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine '#define ABC XYZ(1)' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'ABC', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[5]).toEqual value: 'XYZ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'entity.name.function.c'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'punctuation.section.arguments.begin.bracket.round.c'] - expect(tokens[7]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'constant.numeric.c'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c'] - - {tokens} = grammar.tokenizeLine '#define PI_PLUS_ONE (3.14 + 1)' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'PI_PLUS_ONE', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[6]).toEqual value: '3.14', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] - expect(tokens[8]).toEqual value: '+', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c'] - expect(tokens[10]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] - - describe "macros", -> - it "tokenizes them", -> - {tokens} = grammar.tokenizeLine '#define INCREMENT(x) x++' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'INCREMENT', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(tokens[5]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(tokens[7]).toEqual value: ' x', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[8]).toEqual value: '++', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.increment.c'] - - {tokens} = grammar.tokenizeLine '#define MULT(x, y) (x) * (y)' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'MULT', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(tokens[5]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] - expect(tokens[7]).toEqual value: ' y', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(tokens[9]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[10]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[11]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(tokens[13]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[14]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c'] - expect(tokens[15]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[16]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[17]).toEqual value: 'y', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] - - {tokens} = grammar.tokenizeLine '#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while ( 0 )' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'SWAP', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(tokens[5]).toEqual value: 'a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] - expect(tokens[7]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(tokens[10]).toEqual value: 'do', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.c'] - expect(tokens[12]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(tokens[13]).toEqual value: ' a ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[14]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(tokens[15]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[16]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] - expect(tokens[17]).toEqual value: ' b ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[18]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(tokens[19]).toEqual value: ' a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[20]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] - expect(tokens[21]).toEqual value: ' a ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[22]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(tokens[23]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[24]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] - expect(tokens[25]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[26]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - expect(tokens[28]).toEqual value: 'while', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.c'] - expect(tokens[29]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[30]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[32]).toEqual value: '0', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] - expect(tokens[34]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] - - it "tokenizes multiline macros", -> - lines = grammar.tokenizeLines ''' - #define max(a,b) (a>b)? \\ - a:b - ''' - expect(lines[0][17]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.character.escape.line-continuation.c'] - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.preprocessor.macro.c'] - - lines = grammar.tokenizeLines ''' - #define SWAP(a, b) { \\ - a ^= b; \\ - b ^= a; \\ - a ^= b; \\ - } - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(lines[0][3]).toEqual value: 'SWAP', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(lines[0][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(lines[0][5]).toEqual value: 'a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(lines[0][6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] - expect(lines[0][7]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(lines[0][8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(lines[0][10]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[0][12]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[1][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(lines[1][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[2][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(lines[2][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[3][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(lines[3][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[4][0]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - it "tokenizes complex definitions", -> - lines = grammar.tokenizeLines ''' - #define MakeHook(name) struct HOOK name = {{false, 0L}, \\ - ((HOOKF)(*HookEnt)), ID("hook")} - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(lines[0][3]).toEqual value: 'MakeHook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(lines[0][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(lines[0][5]).toEqual value: 'name', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(lines[0][8]).toEqual value: 'struct', scopes: ['source.c', 'meta.preprocessor.macro.c', 'storage.type.c'] - expect(lines[0][10]).toEqual value: '=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.assignment.c'] - expect(lines[0][12]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[0][13]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[0][14]).toEqual value: 'false', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.language.c'] - expect(lines[0][15]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] - expect(lines[0][17]).toEqual value: '0L', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.numeric.c'] - expect(lines[0][18]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - expect(lines[0][19]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] - expect(lines[0][21]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[1][0]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(lines[1][1]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(lines[1][3]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(lines[1][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(lines[1][5]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.c'] - expect(lines[1][7]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(lines[1][8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(lines[1][9]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] - expect(lines[1][11]).toEqual value: 'ID', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[1][12]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.begin.bracket.round.c'] - expect(lines[1][13]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.begin.c"] - expect(lines[1][14]).toEqual value: 'hook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c'] - expect(lines[1][15]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.end.c"] - expect(lines[1][16]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c'] - expect(lines[1][17]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - describe "includes", -> - it "tokenizes '#include'", -> - {tokens} = grammar.tokenizeLine '#include ' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(tokens[3]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[4]).toEqual value: 'stdio.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] - expect(tokens[5]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '#include' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(tokens[2]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[3]).toEqual value: 'stdio.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] - expect(tokens[4]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '#include_' - expect(tokens[0]).toEqual value: '#include_', scopes: ['source.c'] - - {tokens} = grammar.tokenizeLine '#include "file"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[4]).toEqual value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] - - it "tokenizes '#import'", -> - {tokens} = grammar.tokenizeLine '#import "file"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[4]).toEqual value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] - - it "tokenizes '#include_next'", -> - {tokens} = grammar.tokenizeLine '#include_next "next.h"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'include_next', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[4]).toEqual value: 'next.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] - - describe "diagnostics", -> - it "tokenizes '#error'", -> - {tokens} = grammar.tokenizeLine '#error "C++ compiler required."' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'error', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c'] - expect(tokens[4]).toEqual value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c'] - - it "tokenizes '#warning'", -> - {tokens} = grammar.tokenizeLine '#warning "This is a warning."' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'warning', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c'] - expect(tokens[4]).toEqual value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c'] - - describe "conditionals", -> - it "tokenizes if-elif-else preprocessor blocks", -> - lines = grammar.tokenizeLines ''' - #if defined(CREDIT) - credit(); - #elif defined(DEBIT) - debit(); - #else - printerror(); - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][5]).toEqual value: 'CREDIT', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[1][1]).toEqual value: 'credit', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[1][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(lines[1][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'elif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][5]).toEqual value: 'DEBIT', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[3][1]).toEqual value: 'debit', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[3][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(lines[3][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - expect(lines[4][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[4][1]).toEqual value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[5][1]).toEqual value: 'printerror', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[5][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(lines[5][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - expect(lines[6][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[6][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes if-true-else blocks", -> - lines = grammar.tokenizeLines ''' - #if 1 - int something() { - #if 1 - return 1; - #else - return 0; - #endif - } - #else - int something() { - return 0; - } - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[1][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] - expect(lines[1][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[2][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][2]).toEqual value: 'if', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][4]).toEqual value: '1', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[3][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] - expect(lines[3][3]).toEqual value: '1', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] - expect(lines[4][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[4][2]).toEqual value: 'else', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[5][0]).toEqual value: ' return 0;', scopes: ['source.c', 'meta.block.c', 'comment.block.preprocessor.else-branch.in-block.c'] - expect(lines[6][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[6][2]).toEqual value: 'endif', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[8][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[8][1]).toEqual value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[9][0]).toEqual value: 'int something() {', scopes: ['source.c', 'comment.block.preprocessor.else-branch.c'] - expect(lines[12][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[12][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes if-false-else blocks", -> - lines = grammar.tokenizeLines ''' - int something() { - #if 0 - return 1; - #else - return 0; - #endif - } - ''' - expect(lines[0][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] - expect(lines[0][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[1][2]).toEqual value: 'if', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[1][4]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[2][0]).toEqual value: ' return 1;', scopes: ['source.c', 'meta.block.c', 'comment.block.preprocessor.if-branch.in-block.c'] - expect(lines[3][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[3][2]).toEqual value: 'else', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[4][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] - expect(lines[4][3]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] - expect(lines[5][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[5][2]).toEqual value: 'endif', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - lines = grammar.tokenizeLines ''' - #if 0 - something(); - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '0', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[1][0]).toEqual value: ' something();', scopes: ['source.c', 'comment.block.preprocessor.if-branch.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes ifdef-elif blocks", -> - lines = grammar.tokenizeLines ''' - #ifdef __unix__ /* is defined by compilers targeting Unix systems */ - # include - #elif defined _WIN32 /* is defined by compilers targeting Windows systems */ - # include - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'ifdef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '__unix__', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[0][5]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(lines[0][6]).toEqual value: ' is defined by compilers targeting Unix systems ', scopes: ['source.c', 'comment.block.c'] - expect(lines[0][7]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(lines[1][2]).toEqual value: ' include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(lines[1][4]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] - expect(lines[1][5]).toEqual value: 'unistd.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] - expect(lines[1][6]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'elif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][5]).toEqual value: '_WIN32', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[2][7]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(lines[2][8]).toEqual value: ' is defined by compilers targeting Windows systems ', scopes: ['source.c', 'comment.block.c'] - expect(lines[2][9]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - expect(lines[3][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(lines[3][2]).toEqual value: ' include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(lines[3][4]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] - expect(lines[3][5]).toEqual value: 'windows.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] - expect(lines[3][6]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] - expect(lines[4][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[4][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes ifndef blocks", -> - lines = grammar.tokenizeLines ''' - #ifndef _INCL_GUARD - #define _INCL_GUARD - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'ifndef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(lines[1][2]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(lines[1][4]).toEqual value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "highlights stray elif, else and endif usages as invalid", -> - lines = grammar.tokenizeLines ''' - #if defined SOMEMACRO - #else - #elif //elif not permitted here - #endif - #else //else without if - #endif //endif without if - ''' - expect(lines[2][0]).toEqual value: '#elif', scopes: ['source.c', 'invalid.illegal.stray-elif.c'] - expect(lines[4][0]).toEqual value: '#else', scopes: ['source.c', 'invalid.illegal.stray-else.c'] - expect(lines[5][0]).toEqual value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c'] - - it "highlights errorneous defined usage as invalid", -> - {tokens} = grammar.tokenizeLine '#if defined == VALUE' - expect(tokens[3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c'] - - it "tokenizes multi line conditional queries", -> - lines = grammar.tokenizeLines ''' - #if !defined (MACRO_A) \\ - || !defined MACRO_C - #define MACRO_A TRUE - #elif MACRO_C == (5 + 4 - /* multi line comment */ \\ - SOMEMACRO(TRUE) * 8) // single line comment - #endif - ''' - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] - expect(lines[0][3]).toEqual value: '!', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] - expect(lines[0][7]).toEqual value: 'MACRO_A', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[0][10]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.c', 'constant.character.escape.line-continuation.c'] - expect(lines[1][1]).toEqual value: '||', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] - expect(lines[1][3]).toEqual value: '!', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] - expect(lines[1][4]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[1][6]).toEqual value: 'MACRO_C', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[3][2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] - expect(lines[3][3]).toEqual value: 'MACRO_C', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[3][5]).toEqual value: '==', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.comparison.c'] - expect(lines[3][7]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(lines[3][8]).toEqual value: '5', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[3][10]).toEqual value: '+', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] - expect(lines[3][14]).toEqual value: '-', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] - expect(lines[3][16]).toEqual value: '/*', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(lines[3][17]).toEqual value: ' multi line comment ', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c'] - expect(lines[3][18]).toEqual value: '*/', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - expect(lines[3][20]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.c', 'constant.character.escape.line-continuation.c'] - expect(lines[4][1]).toEqual value: 'SOMEMACRO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[4][3]).toEqual value: 'TRUE', scopes: ['source.c', 'meta.preprocessor.c', 'constant.language.c'] - expect(lines[4][6]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] - expect(lines[4][9]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(lines[4][11]).toEqual value: '//', scopes: ['source.c', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(lines[4][12]).toEqual value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp'] - - it "tokenizes ternary operator usage in preprocessor conditionals", -> - {tokens} = grammar.tokenizeLine '#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)' - expect(tokens[9]).toEqual value: '?', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c'] - expect(tokens[11]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(tokens[17]).toEqual value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c'] - - describe "indentation", -> - editor = null - - beforeEach -> - editor = buildTextEditor() - editor.setGrammar(grammar) - - expectPreservedIndentation = (text) -> - editor.setText(text) - editor.autoIndentBufferRows(0, editor.getLineCount() - 1) - - expectedLines = text.split('\n') - actualLines = editor.getText().split('\n') - for actualLine, i in actualLines - expect([ - actualLine, - editor.indentLevelForLine(actualLine) - ]).toEqual([ - expectedLines[i], - editor.indentLevelForLine(expectedLines[i]) - ]) - - it "indents allman-style curly braces", -> - expectPreservedIndentation ''' - if (a) - { - for (;;) - { - do - { - while (b) - { - c(); - } - } - while (d) - } - } - ''' - - it "indents non-allman-style curly braces", -> - expectPreservedIndentation ''' - if (a) { - for (;;) { - do { - while (b) { - c(); - } - } while (d) - } - } - ''' - - it "indents function arguments", -> - expectPreservedIndentation ''' - a( - b, - c( - d - ) - ); - ''' - - it "indents array and struct literals", -> - expectPreservedIndentation ''' - some_t a[3] = { - { .b = c }, - { .b = c, .d = {1, 2} }, - }; - ''' - - it "tokenizes binary literal", -> - {tokens} = grammar.tokenizeLine '0b101010' - expect(tokens[0]).toEqual value: '0b101010', scopes: ['source.c', 'constant.numeric.c'] - - describe "access", -> - it "tokenizes the dot access operator", -> - lines = grammar.tokenizeLines ''' - { - a. - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - - lines = grammar.tokenizeLines ''' - { - a.b; - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a.b() - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'meta.function-call.c', 'entity.name.function.c'] - - lines = grammar.tokenizeLines ''' - { - a. b; - } - ''' - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a .b; - } - ''' - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a . b; - } - ''' - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - it "tokenizes the pointer access operator", -> - lines = grammar.tokenizeLines ''' - { - a->b; - } - ''' - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a->b() - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - - lines = grammar.tokenizeLines ''' - { - a-> b; - } - ''' - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a ->b; - } - ''' - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a -> b; - } - ''' - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a-> - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - - describe "operators", -> - it "tokenizes the sizeof operator", -> - {tokens} = grammar.tokenizeLine('sizeof unary_expression') - expect(tokens[0]).toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - expect(tokens[1]).toEqual value: ' unary_expression', scopes: ['source.c'] - - {tokens} = grammar.tokenizeLine('sizeof (int)') - expect(tokens[0]).toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - expect(tokens[1]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[3]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] - expect(tokens[4]).toEqual value: ')', scopes: ['source.c', 'punctuation.section.parens.end.bracket.round.c'] - - {tokens} = grammar.tokenizeLine('$sizeof') - expect(tokens[1]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - - {tokens} = grammar.tokenizeLine('sizeof$') - expect(tokens[0]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - - {tokens} = grammar.tokenizeLine('sizeof_') - expect(tokens[0]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - - it "tokenizes the increment operator", -> - {tokens} = grammar.tokenizeLine('i++') - expect(tokens[0]).toEqual value: 'i', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '++', scopes: ['source.c', 'keyword.operator.increment.c'] - - {tokens} = grammar.tokenizeLine('++i') - expect(tokens[0]).toEqual value: '++', scopes: ['source.c', 'keyword.operator.increment.c'] - expect(tokens[1]).toEqual value: 'i', scopes: ['source.c'] - - it "tokenizes the decrement operator", -> - {tokens} = grammar.tokenizeLine('i--') - expect(tokens[0]).toEqual value: 'i', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '--', scopes: ['source.c', 'keyword.operator.decrement.c'] - - {tokens} = grammar.tokenizeLine('--i') - expect(tokens[0]).toEqual value: '--', scopes: ['source.c', 'keyword.operator.decrement.c'] - expect(tokens[1]).toEqual value: 'i', scopes: ['source.c'] - - it "tokenizes logical operators", -> - {tokens} = grammar.tokenizeLine('!a') - expect(tokens[0]).toEqual value: '!', scopes: ['source.c', 'keyword.operator.logical.c'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.c'] - - operators = ['&&', '||'] - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.logical.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes comparison operators", -> - operators = ['<=', '>=', '!=', '==', '<', '>' ] - - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.comparison.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes arithmetic operators", -> - operators = ['+', '-', '*', '/', '%'] - - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes ternary operators", -> - {tokens} = grammar.tokenizeLine('a ? b : c') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' b ', scopes: ['source.c'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[4]).toEqual value: ' c', scopes: ['source.c'] - - it "tokenizes ternary operators with member access", -> - {tokens} = grammar.tokenizeLine('a ? b.c : d') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - expect(tokens[3]).toEqual value: '.', scopes: ['source.c', 'punctuation.separator.dot-access.c'] - expect(tokens[4]).toEqual value: 'c', scopes: ['source.c', 'variable.other.member.c'] - expect(tokens[5]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[6]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[7]).toEqual value: ' d', scopes: ['source.c'] - - it "tokenizes ternary operators with pointer dereferencing", -> - {tokens} = grammar.tokenizeLine('a ? b->c : d') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - expect(tokens[3]).toEqual value: '->', scopes: ['source.c', 'punctuation.separator.pointer-access.c'] - expect(tokens[4]).toEqual value: 'c', scopes: ['source.c', 'variable.other.member.c'] - expect(tokens[5]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[6]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[7]).toEqual value: ' d', scopes: ['source.c'] - - it "tokenizes ternary operators with function invocation", -> - {tokens} = grammar.tokenizeLine('a ? f(b) : c') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[3]).toEqual value: 'f', scopes: ['source.c', 'meta.function-call.c', 'entity.name.function.c'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.begin.bracket.round.c'] - expect(tokens[5]).toEqual value: 'b', scopes: ['source.c', 'meta.function-call.c'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.end.bracket.round.c'] - expect(tokens[7]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[8]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[9]).toEqual value: ' c', scopes: ['source.c'] - - describe "bitwise", -> - it "tokenizes bitwise 'not'", -> - {tokens} = grammar.tokenizeLine('~a') - expect(tokens[0]).toEqual value: '~', scopes: ['source.c', 'keyword.operator.c'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.c'] - - it "tokenizes shift operators", -> - {tokens} = grammar.tokenizeLine('>>') - expect(tokens[0]).toEqual value: '>>', scopes: ['source.c', 'keyword.operator.bitwise.shift.c'] - - {tokens} = grammar.tokenizeLine('<<') - expect(tokens[0]).toEqual value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c'] - - it "tokenizes them", -> - operators = ['|', '^', '&'] - - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - describe "assignment", -> - it "tokenizes the assignment operator", -> - {tokens} = grammar.tokenizeLine('a = b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '=', scopes: ['source.c', 'keyword.operator.assignment.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes compound assignment operators", -> - operators = ['+=', '-=', '*=', '/=', '%='] - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.assignment.compound.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes bitwise compound operators", -> - operators = ['<<=', '>>=', '&=', '^=', '|='] - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - describe "C++", -> - beforeEach -> - grammar = atom.grammars.grammarForScopeName('source.cpp') - - it "parses the grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe 'source.cpp' - - it "tokenizes this with `.this` class", -> - {tokens} = grammar.tokenizeLine 'this.x' - expect(tokens[0]).toEqual value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp'] - - it "tokenizes classes", -> - lines = grammar.tokenizeLines ''' - class Thing { - int x; - } - ''' - expect(lines[0][0]).toEqual value: 'class', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'storage.type.cpp'] - expect(lines[0][2]).toEqual value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp'] - - it "tokenizes 'extern C'", -> - lines = grammar.tokenizeLines ''' - extern "C" { - #include "legacy_C_header.h" - } - ''' - expect(lines[0][0]).toEqual value: 'extern', scopes: ['source.cpp', 'meta.extern-block.cpp', 'storage.modifier.cpp'] - expect(lines[0][2]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[0][3]).toEqual value: 'C', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp'] - expect(lines[0][4]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[0][6]).toEqual value: '{', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[1][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(lines[1][1]).toEqual value: 'include', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(lines[1][3]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] - expect(lines[1][4]).toEqual value: 'legacy_C_header.h', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] - expect(lines[1][5]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] - expect(lines[2][0]).toEqual value: '}', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.end.bracket.curly.c'] - - lines = grammar.tokenizeLines ''' - #ifdef __cplusplus - extern "C" { - #endif - // legacy C code here - #ifdef __cplusplus - } - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '__cplusplus', scopes: ['source.cpp', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[1][0]).toEqual value: 'extern', scopes: ['source.cpp', 'meta.extern-block.cpp', 'storage.modifier.cpp'] - expect(lines[1][2]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[1][3]).toEqual value: 'C', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp'] - expect(lines[1][4]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[1][6]).toEqual value: '{', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[3][1]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(lines[3][2]).toEqual value: ' legacy C code here', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - expect(lines[4][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[4][1]).toEqual value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[5][0]).toEqual value: '}', scopes: ['source.cpp'] - expect(lines[6][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[6][1]).toEqual value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes UTF string escapes", -> - lines = grammar.tokenizeLines ''' - string str = U"\\U01234567\\u0123\\"\\0123\\x123"; - ''' - expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] - expect(lines[0][1]).toEqual value: '=', scopes: ['source.cpp', 'keyword.operator.assignment.c'] - expect(lines[0][3]).toEqual value: 'U', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp', 'meta.encoding.cpp'] - expect(lines[0][4]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[0][5]).toEqual value: '\\U01234567', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][6]).toEqual value: '\\u0123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][7]).toEqual value: '\\"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][8]).toEqual value: '\\012', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][9]).toEqual value: '3', scopes: ['source.cpp', 'string.quoted.double.cpp'] - expect(lines[0][10]).toEqual value: '\\x123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][11]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[0][12]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] - - it "tokenizes % format specifiers", -> - {tokens} = grammar.tokenizeLine '"%d"' - expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(tokens[1]).toEqual value: '%d', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.other.placeholder.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - - {tokens} = grammar.tokenizeLine '"%"' - expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp', 'invalid.illegal.placeholder.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - - {tokens} = grammar.tokenizeLine '"%" PRId32' - expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - - it "tokenizes raw string literals", -> - lines = grammar.tokenizeLines ''' - string str = R"test( - this is \"a\" test 'string' - )test"; - ''' - expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] - expect(lines[0][3]).toEqual value: 'R"test(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[1][0]).toEqual value: ' this is "a" test \'string\'', scopes: ['source.cpp', 'string.quoted.double.raw.cpp'] - expect(lines[2][0]).toEqual value: ')test"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[2][1]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] - - it "errors on long raw string delimiters", -> - lines = grammar.tokenizeLines ''' - string str = R"01234567890123456()01234567890123456"; - ''' - expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] - expect(lines[0][3]).toEqual value: 'R"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[0][4]).toEqual value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp', 'invalid.illegal.delimiter-too-long.cpp'] - expect(lines[0][5]).toEqual value: '(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[0][7]).toEqual value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp', 'invalid.illegal.delimiter-too-long.cpp'] - expect(lines[0][8]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[0][9]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] - - it "tokenizes destructors", -> - {tokens} = grammar.tokenizeLine('~Foo() {}') - expect(tokens[0]).toEqual value: '~Foo', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'entity.name.function.cpp'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c'] - expect(tokens[2]).toEqual value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - {tokens} = grammar.tokenizeLine('Foo::~Bar() {}') - expect(tokens[0]).toEqual value: 'Foo::~Bar', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'entity.name.function.cpp'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c'] - expect(tokens[2]).toEqual value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - describe "digit separators", -> - it "recognizes numbers with digit separators", -> - {tokens} = grammar.tokenizeLine "1'000" - expect(tokens[0]).toEqual value: "1'000", scopes: ['source.cpp', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine "123'456.500'000e-1'5" - expect(tokens[0]).toEqual value: "123'456.500'000e-1'5", scopes: ['source.cpp', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine "0x1234'5678" - expect(tokens[0]).toEqual value: "0x1234'5678", scopes: ['source.cpp', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine "0'123'456" - expect(tokens[0]).toEqual value: "0'123'456", scopes: ['source.cpp', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine "0b1100'0011'1111'0000" - expect(tokens[0]).toEqual value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c'] - - it "does not tokenize single quotes at the beginning or end of numbers as digit separators", -> - {tokens} = grammar.tokenizeLine "'1000" - expect(tokens[0]).toEqual value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: "1000", scopes: ['source.cpp', 'string.quoted.single.c'] - - {tokens} = grammar.tokenizeLine "1000'" - expect(tokens[0]).toEqual value: "1000", scopes: ['source.cpp', 'constant.numeric.c'] - expect(tokens[1]).toEqual value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c'] - - describe "comments", -> - it "tokenizes them", -> - {tokens} = grammar.tokenizeLine '// comment' - expect(tokens[0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(tokens[1]).toEqual value: ' comment', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - - lines = grammar.tokenizeLines ''' - // separated\\ - comment - ''' - expect(lines[0][0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(lines[0][1]).toEqual value: ' separated', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - expect(lines[0][2]).toEqual value: '\\', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'constant.character.escape.line-continuation.c'] - expect(lines[1][0]).toEqual value: 'comment', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - - lines = grammar.tokenizeLines ''' - // The space character \x20 is used to prevent stripping trailing whitespace - // not separated\\\x20 - comment - ''' - expect(lines[1][0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(lines[1][1]).toEqual value: ' not separated\\ ', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - expect(lines[2][0]).toEqual value: 'comment', scopes: ['source.cpp'] - - describe "operators", -> - it "tokenizes ternary operators with namespace resolution", -> - {tokens} = grammar.tokenizeLine('a ? ns::b : ns::c') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.cpp'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.cpp', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' ns', scopes: ['source.cpp'] - expect(tokens[3]).toEqual value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp'] - expect(tokens[4]).toEqual value: 'b ', scopes: ['source.cpp'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.cpp', 'keyword.operator.ternary.c'] - expect(tokens[6]).toEqual value: ' ns', scopes: ['source.cpp'] - expect(tokens[7]).toEqual value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp'] - expect(tokens[8]).toEqual value: 'c', scopes: ['source.cpp'] diff --git a/packages/language-c/spec/c-spec.js b/packages/language-c/spec/c-spec.js index 73b11e3a68..4b5f8df793 100644 --- a/packages/language-c/spec/c-spec.js +++ b/packages/language-c/spec/c-spec.js @@ -32,7 +32,7 @@ describe("Language-C", function() { it("parses the grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe('source.c'); + expect(grammar.scopeName).toBe('source.c'); }); it("tokenizes punctuation", function() { @@ -44,7 +44,7 @@ describe("Language-C", function() { expect(tokens[3]).toEqual({value: ']', scopes: ['source.c', 'punctuation.definition.end.bracket.square.c']}); ({tokens} = grammar.tokenizeLine('a, b')); - return expect(tokens[1]).toEqual({value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c']}); + expect(tokens[1]).toEqual({value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c']}); }); it("tokenizes functions", function() { @@ -62,7 +62,7 @@ int something(int param) { expect(lines[0][8]).toEqual({value: '{', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); expect(lines[1][1]).toEqual({value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c']}); expect(lines[1][3]).toEqual({value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c']}); - return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(lines[2][0]).toEqual({value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); it("tokenizes varargs ellipses", function() { @@ -71,7 +71,7 @@ int something(int param) { expect(tokens[2]).toEqual({value: 'function', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); expect(tokens[3]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); expect(tokens[4]).toEqual({value: '...', scopes: ['source.c', 'meta.function.c', 'punctuation.vararg-ellipses.c']}); - return expect(tokens[5]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); + expect(tokens[5]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); }); it("tokenizes various _t types", function() { @@ -85,14 +85,14 @@ int something(int param) { expect(tokens[0]).toEqual({value: 'int32_t', scopes: ['source.c', 'support.type.stdint.c']}); ({tokens} = grammar.tokenizeLine('myType_t var;')); - return expect(tokens[0]).toEqual({value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c']}); + expect(tokens[0]).toEqual({value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c']}); }); it("tokenizes 'line continuation' character", function() { const {tokens} = grammar.tokenizeLine("ma\\\nin(){};"); expect(tokens[0]).toEqual({value: 'ma', scopes: ['source.c']}); expect(tokens[1]).toEqual({value: '\\', scopes: ['source.c', 'constant.character.escape.line-continuation.c']}); - return expect(tokens[3]).toEqual({value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(tokens[3]).toEqual({value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); }); describe("strings", () => it("tokenizes them", function() { @@ -135,7 +135,7 @@ int something(int param) { ({tokens} = grammar.tokenizeLine('"%" SCNd32')); expect(tokens[0]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); expect(tokens[1]).toEqual({value: '%', scopes: ['source.c', 'string.quoted.double.c']}); - return expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); })); describe("comments", () => it("tokenizes them", function() { @@ -149,7 +149,7 @@ int something(int param) { expect(tokens[2]).toEqual({value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c']}); ({tokens} = grammar.tokenizeLine('*/*')); - return expect(tokens[0]).toEqual({value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c']}); + expect(tokens[0]).toEqual({value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c']}); })); describe("preprocessor directives", function() { @@ -160,7 +160,7 @@ int something(int param) { expect(tokens[3]).toEqual({value: '151', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); expect(tokens[6]).toEqual({value: 'copy.c', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c']}); - return expect(tokens[7]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); }); it("tokenizes '#undef'", function() { @@ -168,7 +168,7 @@ int something(int param) { expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'undef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c']}); expect(tokens[2]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.c']}); - return expect(tokens[3]).toEqual({value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[3]).toEqual({value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); }); it("tokenizes '#pragma'", function() { @@ -190,7 +190,7 @@ int something(int param) { ({tokens} = grammar.tokenizeLine('#pragma mark – Initialization')); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'pragma mark', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c']}); - return expect(tokens[3]).toEqual({value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c']}); + expect(tokens[3]).toEqual({value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c']}); }); describe("define", function() { @@ -198,7 +198,7 @@ int something(int param) { const {tokens} = grammar.tokenizeLine('#define _FILE_NAME_H_'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); - return expect(tokens[3]).toEqual({value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[3]).toEqual({value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); }); it("tokenizes '#define [identifier name] [value]'", function() { @@ -227,10 +227,10 @@ int something(int param) { expect(tokens[6]).toEqual({value: '3.14', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); expect(tokens[8]).toEqual({value: '+', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c']}); expect(tokens[10]).toEqual({value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); - return expect(tokens[11]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(tokens[11]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); }); - return describe("macros", function() { + describe("macros", function() { it("tokenizes them", function() { let {tokens} = grammar.tokenizeLine('#define INCREMENT(x) x++'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); @@ -291,7 +291,7 @@ int something(int param) { expect(tokens[29]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); expect(tokens[30]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c']}); expect(tokens[32]).toEqual({value: '0', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); - return expect(tokens[34]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(tokens[34]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); }); it("tokenizes multiline macros", function() { @@ -327,10 +327,10 @@ int something(int param) { expect(lines[2][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); expect(lines[3][1]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); expect(lines[3][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); - return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(lines[4][0]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); - return it("tokenizes complex definitions", function() { + it("tokenizes complex definitions", function() { const lines = grammar.tokenizeLines(`\ #define MakeHook(name) struct HOOK name = {{false, 0L}, \\ ((HOOKF)(*HookEnt)), ID("hook")}\ @@ -366,7 +366,7 @@ int something(int param) { expect(lines[1][14]).toEqual({value: 'hook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c']}); expect(lines[1][15]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.end.c"]}); expect(lines[1][16]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c']}); - return expect(lines[1][17]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(lines[1][17]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); }); }); @@ -395,7 +395,7 @@ int something(int param) { expect(tokens[1]).toEqual({value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); it("tokenizes '#import'", function() { @@ -404,16 +404,16 @@ int something(int param) { expect(tokens[1]).toEqual({value: 'import', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); - return it("tokenizes '#include_next'", function() { + it("tokenizes '#include_next'", function() { const {tokens} = grammar.tokenizeLine('#include_next "next.h"'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'include_next', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'next.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); }); @@ -422,18 +422,18 @@ int something(int param) { const {tokens} = grammar.tokenizeLine('#error "C++ compiler required."'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'error', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c']}); - return expect(tokens[4]).toEqual({value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); + expect(tokens[4]).toEqual({value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); }); - return it("tokenizes '#warning'", function() { + it("tokenizes '#warning'", function() { const {tokens} = grammar.tokenizeLine('#warning "This is a warning."'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'warning', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c']}); - return expect(tokens[4]).toEqual({value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); + expect(tokens[4]).toEqual({value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); }); }); - return describe("conditionals", function() { + describe("conditionals", function() { it("tokenizes if-elif-else preprocessor blocks", function() { const lines = grammar.tokenizeLines(`\ #if defined(CREDIT) @@ -465,7 +465,7 @@ int something(int param) { expect(lines[5][2]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); expect(lines[5][3]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); expect(lines[6][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes if-true-else blocks", function() { @@ -504,7 +504,7 @@ int something() { expect(lines[8][1]).toEqual({value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); expect(lines[9][0]).toEqual({value: 'int something() {', scopes: ['source.c', 'comment.block.preprocessor.else-branch.c']}); expect(lines[12][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[12][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[12][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes if-false-else blocks", function() { @@ -542,7 +542,7 @@ int something() { expect(lines[0][3]).toEqual({value: '0', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); expect(lines[1][0]).toEqual({value: ' something();', scopes: ['source.c', 'comment.block.preprocessor.if-branch.c']}); expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes ifdef-elif blocks", function() { @@ -578,7 +578,7 @@ int something() { expect(lines[3][5]).toEqual({value: 'windows.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c']}); expect(lines[3][6]).toEqual({value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c']}); expect(lines[4][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[4][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[4][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes ifndef blocks", function() { @@ -595,7 +595,7 @@ int something() { expect(lines[1][2]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); expect(lines[1][4]).toEqual({value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("highlights stray elif, else and endif usages as invalid", function() { @@ -610,12 +610,12 @@ int something() { ); expect(lines[2][0]).toEqual({value: '#elif', scopes: ['source.c', 'invalid.illegal.stray-elif.c']}); expect(lines[4][0]).toEqual({value: '#else', scopes: ['source.c', 'invalid.illegal.stray-else.c']}); - return expect(lines[5][0]).toEqual({value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c']}); + expect(lines[5][0]).toEqual({value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c']}); }); it("highlights errorneous defined usage as invalid", function() { const {tokens} = grammar.tokenizeLine('#if defined == VALUE'); - return expect(tokens[3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c']}); + expect(tokens[3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c']}); }); it("tokenizes multi line conditional queries", function() { @@ -652,14 +652,14 @@ int something() { expect(lines[4][6]).toEqual({value: '*', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c']}); expect(lines[4][9]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.end.bracket.round.c']}); expect(lines[4][11]).toEqual({value: '//', scopes: ['source.c', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); - return expect(lines[4][12]).toEqual({value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp']}); + expect(lines[4][12]).toEqual({value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp']}); }); - return it("tokenizes ternary operator usage in preprocessor conditionals", function() { + it("tokenizes ternary operator usage in preprocessor conditionals", function() { const {tokens} = grammar.tokenizeLine('#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)'); expect(tokens[9]).toEqual({value: '?', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); expect(tokens[11]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); - return expect(tokens[17]).toEqual({value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); + expect(tokens[17]).toEqual({value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); }); }); }); @@ -669,7 +669,7 @@ int something() { beforeEach(function() { editor = buildTextEditor(); - return editor.setGrammar(grammar); + editor.setGrammar(grammar); }); const expectPreservedIndentation = function(text) { @@ -678,7 +678,7 @@ int something() { const expectedLines = text.split('\n'); const actualLines = editor.getText().split('\n'); - return Array.from(actualLines).map((actualLine, i) => + Array.from(actualLines).map((actualLine, i) => expect([ actualLine, editor.indentLevelForLine(actualLine) @@ -737,9 +737,9 @@ some_t a[3] = { ` )); - return it("tokenizes binary literal", function() { + it("tokenizes binary literal", function() { const {tokens} = grammar.tokenizeLine('0b101010'); - return expect(tokens[0]).toEqual({value: '0b101010', scopes: ['source.c', 'constant.numeric.c']}); + expect(tokens[0]).toEqual({value: '0b101010', scopes: ['source.c', 'constant.numeric.c']}); }); }); @@ -799,10 +799,10 @@ some_t a[3] = { ` ); expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); - return expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); }); - return it("tokenizes the pointer access operator", function() { + it("tokenizes the pointer access operator", function() { let lines = grammar.tokenizeLines(`\ { a->b; @@ -855,11 +855,11 @@ some_t a[3] = { ` ); expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.block.c']}); - return expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); }); }); - return describe("operators", function() { + describe("operators", function() { it("tokenizes the sizeof operator", function() { let {tokens} = grammar.tokenizeLine('sizeof unary_expression'); expect(tokens[0]).toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); @@ -879,7 +879,7 @@ some_t a[3] = { expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); ({tokens} = grammar.tokenizeLine('sizeof_')); - return expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); + expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); }); it("tokenizes the increment operator", function() { @@ -889,7 +889,7 @@ some_t a[3] = { ({tokens} = grammar.tokenizeLine('++i')); expect(tokens[0]).toEqual({value: '++', scopes: ['source.c', 'keyword.operator.increment.c']}); - return expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); }); it("tokenizes the decrement operator", function() { @@ -899,7 +899,7 @@ some_t a[3] = { ({tokens} = grammar.tokenizeLine('--i')); expect(tokens[0]).toEqual({value: '--', scopes: ['source.c', 'keyword.operator.decrement.c']}); - return expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); }); it("tokenizes logical operators", function() { @@ -956,7 +956,7 @@ some_t a[3] = { expect(tokens[1]).toEqual({value: '?', scopes: ['source.c', 'keyword.operator.ternary.c']}); expect(tokens[2]).toEqual({value: ' b ', scopes: ['source.c']}); expect(tokens[3]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - return expect(tokens[4]).toEqual({value: ' c', scopes: ['source.c']}); + expect(tokens[4]).toEqual({value: ' c', scopes: ['source.c']}); }); it("tokenizes ternary operators with member access", function() { @@ -968,7 +968,7 @@ some_t a[3] = { expect(tokens[4]).toEqual({value: 'c', scopes: ['source.c', 'variable.other.member.c']}); expect(tokens[5]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[6]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - return expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); + expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); }); it("tokenizes ternary operators with pointer dereferencing", function() { @@ -980,7 +980,7 @@ some_t a[3] = { expect(tokens[4]).toEqual({value: 'c', scopes: ['source.c', 'variable.other.member.c']}); expect(tokens[5]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[6]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - return expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); + expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); }); it("tokenizes ternary operators with function invocation", function() { @@ -994,14 +994,14 @@ some_t a[3] = { expect(tokens[6]).toEqual({value: ')', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.end.bracket.round.c']}); expect(tokens[7]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[8]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - return expect(tokens[9]).toEqual({value: ' c', scopes: ['source.c']}); + expect(tokens[9]).toEqual({value: ' c', scopes: ['source.c']}); }); describe("bitwise", function() { it("tokenizes bitwise 'not'", function() { const {tokens} = grammar.tokenizeLine('~a'); expect(tokens[0]).toEqual({value: '~', scopes: ['source.c', 'keyword.operator.c']}); - return expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c']}); }); it("tokenizes shift operators", function() { @@ -1009,10 +1009,10 @@ some_t a[3] = { expect(tokens[0]).toEqual({value: '>>', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); ({tokens} = grammar.tokenizeLine('<<')); - return expect(tokens[0]).toEqual({value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); + expect(tokens[0]).toEqual({value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); }); - return it("tokenizes them", function() { + it("tokenizes them", function() { const operators = ['|', '^', '&']; return (() => { @@ -1028,12 +1028,12 @@ some_t a[3] = { }); }); - return describe("assignment", function() { + describe("assignment", function() { it("tokenizes the assignment operator", function() { const {tokens} = grammar.tokenizeLine('a = b'); expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); expect(tokens[1]).toEqual({value: '=', scopes: ['source.c', 'keyword.operator.assignment.c']}); - return expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); + expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); }); it("tokenizes compound assignment operators", function() { @@ -1050,7 +1050,7 @@ some_t a[3] = { })(); }); - return it("tokenizes bitwise compound operators", function() { + it("tokenizes bitwise compound operators", function() { const operators = ['<<=', '>>=', '&=', '^=', '|=']; return (() => { const result = []; @@ -1067,17 +1067,17 @@ some_t a[3] = { }); }); - return describe("C++", function() { + describe("C++", function() { beforeEach(() => grammar = atom.grammars.grammarForScopeName('source.cpp')); it("parses the grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe('source.cpp'); + expect(grammar.scopeName).toBe('source.cpp'); }); it("tokenizes this with `.this` class", function() { const {tokens} = grammar.tokenizeLine('this.x'); - return expect(tokens[0]).toEqual({value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp']}); + expect(tokens[0]).toEqual({value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp']}); }); it("tokenizes classes", function() { @@ -1088,7 +1088,7 @@ class Thing { ` ); expect(lines[0][0]).toEqual({value: 'class', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'storage.type.cpp']}); - return expect(lines[0][2]).toEqual({value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp']}); + expect(lines[0][2]).toEqual({value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp']}); }); it("tokenizes 'extern C'", function() { @@ -1136,7 +1136,7 @@ extern "C" { expect(lines[4][1]).toEqual({value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); expect(lines[5][0]).toEqual({value: '}', scopes: ['source.cpp']}); expect(lines[6][0]).toEqual({value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes UTF string escapes", function() { @@ -1155,7 +1155,7 @@ string str = U"\\U01234567\\u0123\\"\\0123\\x123";\ expect(lines[0][9]).toEqual({value: '3', scopes: ['source.cpp', 'string.quoted.double.cpp']}); expect(lines[0][10]).toEqual({value: '\\x123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp']}); expect(lines[0][11]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); - return expect(lines[0][12]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + expect(lines[0][12]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("tokenizes % format specifiers", function() { @@ -1172,7 +1172,7 @@ string str = U"\\U01234567\\u0123\\"\\0123\\x123";\ ({tokens} = grammar.tokenizeLine('"%" PRId32')); expect(tokens[0]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); expect(tokens[1]).toEqual({value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp']}); - return expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); }); it("tokenizes raw string literals", function() { @@ -1186,7 +1186,7 @@ string str = R"test( expect(lines[0][3]).toEqual({value: 'R"test(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp']}); expect(lines[1][0]).toEqual({value: ' this is "a" test \'string\'', scopes: ['source.cpp', 'string.quoted.double.raw.cpp']}); expect(lines[2][0]).toEqual({value: ')test"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); - return expect(lines[2][1]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + expect(lines[2][1]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("errors on long raw string delimiters", function() { @@ -1201,7 +1201,7 @@ string str = R"01234567890123456()01234567890123456";\ expect(lines[0][6]).toEqual({value: ')', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); expect(lines[0][7]).toEqual({value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp', 'invalid.illegal.delimiter-too-long.cpp']}); expect(lines[0][8]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); - return expect(lines[0][9]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + expect(lines[0][9]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("tokenizes destructors", function() { @@ -1217,7 +1217,7 @@ string str = R"01234567890123456()01234567890123456";\ expect(tokens[1]).toEqual({value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c']}); expect(tokens[2]).toEqual({value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c']}); expect(tokens[4]).toEqual({value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); - return expect(tokens[5]).toEqual({value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); describe("digit separators", function() { @@ -1235,17 +1235,17 @@ string str = R"01234567890123456()01234567890123456";\ expect(tokens[0]).toEqual({value: "0'123'456", scopes: ['source.cpp', 'constant.numeric.c']}); ({tokens} = grammar.tokenizeLine("0b1100'0011'1111'0000")); - return expect(tokens[0]).toEqual({value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c']}); + expect(tokens[0]).toEqual({value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c']}); }); - return it("does not tokenize single quotes at the beginning or end of numbers as digit separators", function() { + it("does not tokenize single quotes at the beginning or end of numbers as digit separators", function() { let {tokens} = grammar.tokenizeLine("'1000"); expect(tokens[0]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); expect(tokens[1]).toEqual({value: "1000", scopes: ['source.cpp', 'string.quoted.single.c']}); ({tokens} = grammar.tokenizeLine("1000'")); expect(tokens[0]).toEqual({value: "1000", scopes: ['source.cpp', 'constant.numeric.c']}); - return expect(tokens[1]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); }); }); @@ -1272,10 +1272,10 @@ comment\ ); expect(lines[1][0]).toEqual({value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); expect(lines[1][1]).toEqual({value: ' not separated\\ ', scopes: ['source.cpp', 'comment.line.double-slash.cpp']}); - return expect(lines[2][0]).toEqual({value: 'comment', scopes: ['source.cpp']}); + expect(lines[2][0]).toEqual({value: 'comment', scopes: ['source.cpp']}); })); - return describe("operators", () => it("tokenizes ternary operators with namespace resolution", function() { + describe("operators", () => it("tokenizes ternary operators with namespace resolution", function() { const {tokens} = grammar.tokenizeLine('a ? ns::b : ns::c'); expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.cpp']}); expect(tokens[1]).toEqual({value: '?', scopes: ['source.cpp', 'keyword.operator.ternary.c']}); @@ -1285,7 +1285,7 @@ comment\ expect(tokens[5]).toEqual({value: ':', scopes: ['source.cpp', 'keyword.operator.ternary.c']}); expect(tokens[6]).toEqual({value: ' ns', scopes: ['source.cpp']}); expect(tokens[7]).toEqual({value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp']}); - return expect(tokens[8]).toEqual({value: 'c', scopes: ['source.cpp']}); + expect(tokens[8]).toEqual({value: 'c', scopes: ['source.cpp']}); })); }); }); From b40c1e3f5e6d9c3c0638fdf87a1ea36e21828472 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 17:59:45 -0700 Subject: [PATCH 03/18] `language-c` remove decaf suggestions --- packages/language-c/spec/c-spec.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/language-c/spec/c-spec.js b/packages/language-c/spec/c-spec.js index 4b5f8df793..066edf31d3 100644 --- a/packages/language-c/spec/c-spec.js +++ b/packages/language-c/spec/c-spec.js @@ -1,11 +1,4 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS205: Consider reworking code to avoid use of IIFEs - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + let TextEditor = null; const buildTextEditor = function(params) { if (atom.workspace.buildTextEditor != null) { From c66487b7dfa7a3c02b5796cf19b396c005eb06ae Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 18:01:27 -0700 Subject: [PATCH 04/18] Decaf `language-clojure` --- .../language-clojure/spec/clojure-spec.coffee | 394 ------------------ .../language-clojure/spec/clojure-spec.js | 55 ++- 2 files changed, 24 insertions(+), 425 deletions(-) delete mode 100644 packages/language-clojure/spec/clojure-spec.coffee diff --git a/packages/language-clojure/spec/clojure-spec.coffee b/packages/language-clojure/spec/clojure-spec.coffee deleted file mode 100644 index 8833ee2638..0000000000 --- a/packages/language-clojure/spec/clojure-spec.coffee +++ /dev/null @@ -1,394 +0,0 @@ -describe "Clojure grammar", -> - grammar = null - - beforeEach -> - atom.config.set('core.useTreeSitterParsers', false) - atom.config.set('core.useExperimentalModernTreeSitter', false) - - waitsForPromise -> - atom.packages.activatePackage("language-clojure") - - runs -> - grammar = atom.grammars.grammarForScopeName("source.clojure") - - it "parses the grammar", -> - expect(grammar).toBeDefined() - expect(grammar.scopeName).toBe "source.clojure" - - it "tokenizes semicolon comments", -> - {tokens} = grammar.tokenizeLine "; clojure" - expect(tokens[0]).toEqual value: ";", scopes: ["source.clojure", "comment.line.semicolon.clojure", "punctuation.definition.comment.clojure"] - expect(tokens[1]).toEqual value: " clojure", scopes: ["source.clojure", "comment.line.semicolon.clojure"] - - it "does not tokenize escaped semicolons as comments", -> - {tokens} = grammar.tokenizeLine "\\; clojure" - expect(tokens[0]).toEqual value: "\\; ", scopes: ["source.clojure"] - expect(tokens[1]).toEqual value: "clojure", scopes: ["source.clojure", "meta.symbol.clojure"] - - it "tokenizes shebang comments", -> - {tokens} = grammar.tokenizeLine "#!/usr/bin/env clojure" - expect(tokens[0]).toEqual value: "#!", scopes: ["source.clojure", "comment.line.shebang.clojure", "punctuation.definition.comment.shebang.clojure"] - expect(tokens[1]).toEqual value: "/usr/bin/env clojure", scopes: ["source.clojure", "comment.line.shebang.clojure"] - - it "tokenizes strings", -> - {tokens} = grammar.tokenizeLine '"foo bar"' - expect(tokens[0]).toEqual value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.begin.clojure"] - expect(tokens[1]).toEqual value: 'foo bar', scopes: ["source.clojure", "string.quoted.double.clojure"] - expect(tokens[2]).toEqual value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.end.clojure"] - - it "tokenizes character escape sequences", -> - {tokens} = grammar.tokenizeLine '"\\n"' - expect(tokens[0]).toEqual value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.begin.clojure"] - expect(tokens[1]).toEqual value: '\\n', scopes: ["source.clojure", "string.quoted.double.clojure", "constant.character.escape.clojure"] - expect(tokens[2]).toEqual value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.end.clojure"] - - it "tokenizes regexes", -> - {tokens} = grammar.tokenizeLine '#"foo"' - expect(tokens[0]).toEqual value: '#"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.begin.clojure"] - expect(tokens[1]).toEqual value: 'foo', scopes: ["source.clojure", "string.regexp.clojure"] - expect(tokens[2]).toEqual value: '"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.end.clojure"] - - it "tokenizes backslash escape character in regexes", -> - {tokens} = grammar.tokenizeLine '#"\\\\" "/"' - expect(tokens[0]).toEqual value: '#"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.begin.clojure"] - expect(tokens[1]).toEqual value: "\\\\", scopes: ['source.clojure', 'string.regexp.clojure', 'constant.character.escape.clojure'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.clojure', 'string.regexp.clojure', "punctuation.definition.regexp.end.clojure"] - expect(tokens[4]).toEqual value: '"', scopes: ['source.clojure', 'string.quoted.double.clojure', 'punctuation.definition.string.begin.clojure'] - expect(tokens[5]).toEqual value: "/", scopes: ['source.clojure', 'string.quoted.double.clojure'] - expect(tokens[6]).toEqual value: '"', scopes: ['source.clojure', 'string.quoted.double.clojure', 'punctuation.definition.string.end.clojure'] - - it "tokenizes escaped double quote in regexes", -> - {tokens} = grammar.tokenizeLine '#"\\""' - expect(tokens[0]).toEqual value: '#"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.begin.clojure"] - expect(tokens[1]).toEqual value: '\\"', scopes: ['source.clojure', 'string.regexp.clojure', 'constant.character.escape.clojure'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.clojure', 'string.regexp.clojure', "punctuation.definition.regexp.end.clojure"] - - it "tokenizes numerics", -> - numbers = - "constant.numeric.ratio.clojure": ["1/2", "123/456", "+0/2", "-23/1"] - "constant.numeric.arbitrary-radix.clojure": ["2R1011", "16rDEADBEEF", "16rDEADBEEFN", "36rZebra"] - "constant.numeric.hexadecimal.clojure": ["0xDEADBEEF", "0XDEADBEEF", "0xDEADBEEFN", "0x0"] - "constant.numeric.octal.clojure": ["0123", "0123N", "00"] - "constant.numeric.double.clojure": ["123.45", "123.45e6", "123.45E6", "123.456M", "42.", "42.M", "42E+9M", "42E-0", "0M", "+0M", "42.E-23M"] - "constant.numeric.long.clojure": ["123", "12321", "123N", "+123N", "-123", "0"] - "constant.numeric.symbol.clojure": ["##Inf", "##-Inf", "##NaN"] - - for scope, nums of numbers - for num in nums - {tokens} = grammar.tokenizeLine num - expect(tokens[0]).toEqual value: num, scopes: ["source.clojure", scope] - - it "tokenizes booleans", -> - booleans = - "constant.language.boolean.clojure": ["true", "false"] - - for scope, bools of booleans - for bool in bools - {tokens} = grammar.tokenizeLine bool - expect(tokens[0]).toEqual value: bool, scopes: ["source.clojure", scope] - - it "tokenizes nil", -> - {tokens} = grammar.tokenizeLine "nil" - expect(tokens[0]).toEqual value: "nil", scopes: ["source.clojure", "constant.language.nil.clojure"] - - it "tokenizes keywords", -> - tests = - "meta.expression.clojure": ["(:foo)"] - "meta.map.clojure": ["{:foo}"] - "meta.vector.clojure": ["[:foo]"] - "meta.quoted-expression.clojure": ["'(:foo)", "`(:foo)"] - - for metaScope, lines of tests - for line in lines - {tokens} = grammar.tokenizeLine line - expect(tokens[1]).toEqual value: ":foo", scopes: ["source.clojure", metaScope, "constant.keyword.clojure"] - - {tokens} = grammar.tokenizeLine "(def foo :bar)" - expect(tokens[5]).toEqual value: ":bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "constant.keyword.clojure"] - - # keywords can start with an uppercase non-ASCII letter - {tokens} = grammar.tokenizeLine "(def foo :Öπ)" - expect(tokens[5]).toEqual value: ":Öπ", scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "constant.keyword.clojure"] - - it "tokenizes keyfns (keyword control)", -> - keyfns = ["declare", "declare-", "ns", "in-ns", "import", "use", "require", "load", "compile", "def", "defn", "defn-", "defmacro", "defåπç"] - - for keyfn in keyfns - {tokens} = grammar.tokenizeLine "(#{keyfn})" - expect(tokens[1]).toEqual value: keyfn, scopes: ["source.clojure", "meta.expression.clojure", "keyword.control.clojure"] - - it "tokenizes keyfns (storage control)", -> - keyfns = ["if", "when", "for", "cond", "do", "let", "binding", "loop", "recur", "fn", "throw", "try", "catch", "finally", "case"] - - for keyfn in keyfns - {tokens} = grammar.tokenizeLine "(#{keyfn})" - expect(tokens[1]).toEqual value: keyfn, scopes: ["source.clojure", "meta.expression.clojure", "storage.control.clojure"] - - it "tokenizes global definitions", -> - macros = ["ns", "declare", "def", "defn", "defn-", "defroutes", "compojure/defroutes", "rum.core/defc123-", "some.nested-ns/def-nested->symbol!?*", "def+!.?abc8:<>", "ns/def+!.?abc8:<>", "ns/defåÄÖπç"] - - for macro in macros - {tokens} = grammar.tokenizeLine "(#{macro} foo 'bar)" - expect(tokens[1]).toEqual value: macro, scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "keyword.control.clojure"] - expect(tokens[3]).toEqual value: "foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "entity.global.clojure"] - - it "tokenizes dynamic variables", -> - mutables = ["*ns*", "*foo-bar*", "*åÄÖπç*"] - - for mutable in mutables - {tokens} = grammar.tokenizeLine mutable - expect(tokens[0]).toEqual value: mutable, scopes: ["source.clojure", "meta.symbol.dynamic.clojure"] - - it "tokenizes metadata", -> - {tokens} = grammar.tokenizeLine "^Foo" - expect(tokens[0]).toEqual value: "^", scopes: ["source.clojure", "meta.metadata.simple.clojure"] - expect(tokens[1]).toEqual value: "Foo", scopes: ["source.clojure", "meta.metadata.simple.clojure", "meta.symbol.clojure"] - - # non-ASCII letters - {tokens} = grammar.tokenizeLine "^Öπ" - expect(tokens[0]).toEqual value: "^", scopes: ["source.clojure", "meta.metadata.simple.clojure"] - expect(tokens[1]).toEqual value: "Öπ", scopes: ["source.clojure", "meta.metadata.simple.clojure", "meta.symbol.clojure"] - - {tokens} = grammar.tokenizeLine "^{:foo true}" - expect(tokens[0]).toEqual value: "^{", scopes: ["source.clojure", "meta.metadata.map.clojure", "punctuation.section.metadata.map.begin.clojure"] - expect(tokens[1]).toEqual value: ":foo", scopes: ["source.clojure", "meta.metadata.map.clojure", "constant.keyword.clojure"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.clojure", "meta.metadata.map.clojure"] - expect(tokens[3]).toEqual value: "true", scopes: ["source.clojure", "meta.metadata.map.clojure", "constant.language.boolean.clojure"] - expect(tokens[4]).toEqual value: "}", scopes: ["source.clojure", "meta.metadata.map.clojure", "punctuation.section.metadata.map.end.trailing.clojure"] - - it "tokenizes functions", -> - expressions = ["(foo)", "(foo 1 10)"] - - for expr in expressions - {tokens} = grammar.tokenizeLine expr - expect(tokens[1]).toEqual value: "foo", scopes: ["source.clojure", "meta.expression.clojure", "entity.name.function.clojure"] - - #non-ASCII letters - {tokens} = grammar.tokenizeLine "(Öπ 2 20)" - expect(tokens[1]).toEqual value: "Öπ", scopes: ["source.clojure", "meta.expression.clojure", "entity.name.function.clojure"] - - it "tokenizes vars", -> - {tokens} = grammar.tokenizeLine "(func #'foo)" - expect(tokens[2]).toEqual value: " #", scopes: ["source.clojure", "meta.expression.clojure"] - expect(tokens[3]).toEqual value: "'foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.var.clojure"] - - # non-ASCII letters - {tokens} = grammar.tokenizeLine "(func #'Öπ)" - expect(tokens[2]).toEqual value: " #", scopes: ["source.clojure", "meta.expression.clojure"] - expect(tokens[3]).toEqual value: "'Öπ", scopes: ["source.clojure", "meta.expression.clojure", "meta.var.clojure"] - - it "tokenizes symbols", -> - {tokens} = grammar.tokenizeLine "x" - expect(tokens[0]).toEqual value: "x", scopes: ["source.clojure", "meta.symbol.clojure"] - - # non-ASCII letters - {tokens} = grammar.tokenizeLine "Öπ" - expect(tokens[0]).toEqual value: "Öπ", scopes: ["source.clojure", "meta.symbol.clojure"] - - # Should not be tokenized as a symbol - {tokens} = grammar.tokenizeLine "1foobar" - expect(tokens[0]).toEqual value: "1", scopes: ["source.clojure", "constant.numeric.long.clojure"] - - it "tokenizes namespaces", -> - {tokens} = grammar.tokenizeLine "foo/bar" - expect(tokens[0]).toEqual value: "foo", scopes: ["source.clojure", "meta.symbol.namespace.clojure"] - expect(tokens[1]).toEqual value: "/", scopes: ["source.clojure"] - expect(tokens[2]).toEqual value: "bar", scopes: ["source.clojure", "meta.symbol.clojure"] - - # non-ASCII letters - {tokens} = grammar.tokenizeLine "Öπ/Åä" - expect(tokens[0]).toEqual value: "Öπ", scopes: ["source.clojure", "meta.symbol.namespace.clojure"] - expect(tokens[1]).toEqual value: "/", scopes: ["source.clojure"] - expect(tokens[2]).toEqual value: "Åä", scopes: ["source.clojure", "meta.symbol.clojure"] - - testMetaSection = (metaScope, puncScope, startsWith, endsWith) -> - # Entire expression on one line. - {tokens} = grammar.tokenizeLine "#{startsWith}foo, bar#{endsWith}" - - [start, mid..., end] = tokens - - expect(start).toEqual value: startsWith, scopes: ["source.clojure", "meta.#{metaScope}.clojure", "punctuation.section.#{puncScope}.begin.clojure"] - expect(end).toEqual value: endsWith, scopes: ["source.clojure", "meta.#{metaScope}.clojure", "punctuation.section.#{puncScope}.end.trailing.clojure"] - - for token in mid - expect(token.scopes.slice(0, 2)).toEqual ["source.clojure", "meta.#{metaScope}.clojure"] - - # Expression broken over multiple lines. - tokens = grammar.tokenizeLines("#{startsWith}foo\n bar#{endsWith}") - - [start, mid..., after] = tokens[0] - - expect(start).toEqual value: startsWith, scopes: ["source.clojure", "meta.#{metaScope}.clojure", "punctuation.section.#{puncScope}.begin.clojure"] - - for token in mid - expect(token.scopes.slice(0, 2)).toEqual ["source.clojure", "meta.#{metaScope}.clojure"] - - [mid..., end] = tokens[1] - - expect(end).toEqual value: endsWith, scopes: ["source.clojure", "meta.#{metaScope}.clojure", "punctuation.section.#{puncScope}.end.trailing.clojure"] - - for token in mid - expect(token.scopes.slice(0, 2)).toEqual ["source.clojure", "meta.#{metaScope}.clojure"] - - it "tokenizes expressions", -> - testMetaSection "expression", "expression", "(", ")" - - it "tokenizes quoted expressions", -> - testMetaSection "quoted-expression", "expression", "'(", ")" - testMetaSection "quoted-expression", "expression", "`(", ")" - - it "tokenizes vectors", -> - testMetaSection "vector", "vector", "[", "]" - - it "tokenizes maps", -> - testMetaSection "map", "map", "{", "}" - - it "tokenizes sets", -> - testMetaSection "set", "set", "\#{", "}" - - it "tokenizes functions in nested sexp", -> - {tokens} = grammar.tokenizeLine "((foo bar) baz)" - expect(tokens[0]).toEqual value: "(", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.begin.clojure"] - expect(tokens[1]).toEqual value: "(", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "punctuation.section.expression.begin.clojure"] - expect(tokens[2]).toEqual value: "foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "entity.name.function.clojure"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure"] - expect(tokens[4]).toEqual value: "bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "meta.symbol.clojure"] - expect(tokens[5]).toEqual value: ")", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "punctuation.section.expression.end.clojure"] - expect(tokens[6]).toEqual value: " ", scopes: ["source.clojure", "meta.expression.clojure"] - expect(tokens[7]).toEqual value: "baz", scopes: ["source.clojure", "meta.expression.clojure", "meta.symbol.clojure"] - expect(tokens[8]).toEqual value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"] - - it "tokenizes maps used as functions", -> - {tokens} = grammar.tokenizeLine "({:foo bar} :foo)" - expect(tokens[0]).toEqual value: "(", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.begin.clojure"] - expect(tokens[1]).toEqual value: "{", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "punctuation.section.map.begin.clojure"] - expect(tokens[2]).toEqual value: ":foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "constant.keyword.clojure"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure"] - expect(tokens[4]).toEqual value: "bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "meta.symbol.clojure"] - expect(tokens[5]).toEqual value: "}", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "punctuation.section.map.end.clojure"] - expect(tokens[6]).toEqual value: " ", scopes: ["source.clojure", "meta.expression.clojure"] - expect(tokens[7]).toEqual value: ":foo", scopes: ["source.clojure", "meta.expression.clojure", "constant.keyword.clojure"] - expect(tokens[8]).toEqual value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"] - - it "tokenizes sets used in functions", -> - {tokens} = grammar.tokenizeLine "(\#{:foo :bar})" - expect(tokens[0]).toEqual value: "(", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.begin.clojure"] - expect(tokens[1]).toEqual value: "\#{", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "punctuation.section.set.begin.clojure"] - expect(tokens[2]).toEqual value: ":foo", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "constant.keyword.clojure"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure"] - expect(tokens[4]).toEqual value: ":bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "constant.keyword.clojure"] - expect(tokens[5]).toEqual value: "}", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "punctuation.section.set.end.trailing.clojure"] - expect(tokens[6]).toEqual value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"] - - describe "firstLineMatch", -> - it "recognises interpreter directives", -> - valid = """ - #!/usr/sbin/boot foo - #!/usr/bin/boot foo=bar/ - #!/usr/sbin/boot - #!/usr/sbin/boot foo bar baz - #!/usr/bin/boot perl - #!/usr/bin/boot bin/perl - #!/usr/bin/boot - #!/bin/boot - #!/usr/bin/boot --script=usr/bin - #! /usr/bin/env A=003 B=149 C=150 D=xzd E=base64 F=tar G=gz H=head I=tail boot - #!\t/usr/bin/env --foo=bar boot --quu=quux - #! /usr/bin/boot - #!/usr/bin/env boot - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - \x20#!/usr/sbin/boot - \t#!/usr/sbin/boot - #!/usr/bin/env-boot/node-env/ - #!/usr/bin/das-boot - #! /usr/binboot - #!\t/usr/bin/env --boot=bar - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - it "recognises Emacs modelines", -> - valid = """ - #-*- Clojure -*- - #-*- mode: ClojureScript -*- - /* -*-clojureScript-*- */ - // -*- Clojure -*- - /* -*- mode:Clojure -*- */ - // -*- font:bar;mode:Clojure -*- - // -*- font:bar;mode:Clojure;foo:bar; -*- - // -*-font:mode;mode:Clojure-*- - // -*- foo:bar mode: clojureSCRIPT bar:baz -*- - " -*-foo:bar;mode:clojure;bar:foo-*- "; - " -*-font-mode:foo;mode:clojure;foo-bar:quux-*-" - "-*-font:x;foo:bar; mode : clojure; bar:foo;foooooo:baaaaar;fo:ba;-*-"; - "-*- font:x;foo : bar ; mode : ClojureScript ; bar : foo ; foooooo:baaaaar;fo:ba-*-"; - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - /* --*clojure-*- */ - /* -*-- clojure -*- - /* -*- -- Clojure -*- - /* -*- Clojure -;- -*- - // -*- iClojure -*- - // -*- Clojure; -*- - // -*- clojure-door -*- - /* -*- model:clojure -*- - /* -*- indent-mode:clojure -*- - // -*- font:mode;Clojure -*- - // -*- mode: -*- Clojure - // -*- mode: das-clojure -*- - // -*-font:mode;mode:clojure--*- - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - it "recognises Vim modelines", -> - valid = """ - vim: se filetype=clojure: - # vim: se ft=clojure: - # vim: set ft=Clojure: - # vim: set filetype=Clojure: - # vim: ft=Clojure - # vim: syntax=Clojure - # vim: se syntax=Clojure: - # ex: syntax=Clojure - # vim:ft=clojure - # vim600: ft=clojure - # vim>600: set ft=clojure: - # vi:noai:sw=3 ts=6 ft=clojure - # vi::::::::::noai:::::::::::: ft=clojure - # vim:ts=4:sts=4:sw=4:noexpandtab:ft=clojure - # vi:: noai : : : : sw =3 ts =6 ft =clojure - # vim: ts=4: pi sts=4: ft=clojure: noexpandtab: sw=4: - # vim: ts=4 sts=4: ft=clojure noexpandtab: - # vim:noexpandtab sts=4 ft=clojure ts=4 - # vim:noexpandtab:ft=clojure - # vim:ts=4:sts=4 ft=clojure:noexpandtab:\x20 - # vim:noexpandtab titlestring=hi\|there\\\\ ft=clojure ts=4 - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - ex: se filetype=clojure: - _vi: se filetype=clojure: - vi: se filetype=clojure - # vim set ft=klojure - # vim: soft=clojure - # vim: clean-syntax=clojure: - # vim set ft=clojure: - # vim: setft=clojure: - # vim: se ft=clojure backupdir=tmp - # vim: set ft=clojure set cmdheight=1 - # vim:noexpandtab sts:4 ft:clojure ts:4 - # vim:noexpandtab titlestring=hi\\|there\\ ft=clojure ts=4 - # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=clojure ts=4 - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() diff --git a/packages/language-clojure/spec/clojure-spec.js b/packages/language-clojure/spec/clojure-spec.js index 2dc1309089..bf7cb0a465 100644 --- a/packages/language-clojure/spec/clojure-spec.js +++ b/packages/language-clojure/spec/clojure-spec.js @@ -1,11 +1,4 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS201: Simplify complex destructure assignments - * DS205: Consider reworking code to avoid use of IIFEs - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe("Clojure grammar", function() { let grammar = null; @@ -15,51 +8,51 @@ describe("Clojure grammar", function() { waitsForPromise(() => atom.packages.activatePackage("language-clojure")); - return runs(() => grammar = atom.grammars.grammarForScopeName("source.clojure")); + runs(() => grammar = atom.grammars.grammarForScopeName("source.clojure")); }); it("parses the grammar", function() { expect(grammar).toBeDefined(); - return expect(grammar.scopeName).toBe("source.clojure"); + expect(grammar.scopeName).toBe("source.clojure"); }); it("tokenizes semicolon comments", function() { const {tokens} = grammar.tokenizeLine("; clojure"); expect(tokens[0]).toEqual({value: ";", scopes: ["source.clojure", "comment.line.semicolon.clojure", "punctuation.definition.comment.clojure"]}); - return expect(tokens[1]).toEqual({value: " clojure", scopes: ["source.clojure", "comment.line.semicolon.clojure"]}); + expect(tokens[1]).toEqual({value: " clojure", scopes: ["source.clojure", "comment.line.semicolon.clojure"]}); }); it("does not tokenize escaped semicolons as comments", function() { const {tokens} = grammar.tokenizeLine("\\; clojure"); expect(tokens[0]).toEqual({value: "\\; ", scopes: ["source.clojure"]}); - return expect(tokens[1]).toEqual({value: "clojure", scopes: ["source.clojure", "meta.symbol.clojure"]}); + expect(tokens[1]).toEqual({value: "clojure", scopes: ["source.clojure", "meta.symbol.clojure"]}); }); it("tokenizes shebang comments", function() { const {tokens} = grammar.tokenizeLine("#!/usr/bin/env clojure"); expect(tokens[0]).toEqual({value: "#!", scopes: ["source.clojure", "comment.line.shebang.clojure", "punctuation.definition.comment.shebang.clojure"]}); - return expect(tokens[1]).toEqual({value: "/usr/bin/env clojure", scopes: ["source.clojure", "comment.line.shebang.clojure"]}); + expect(tokens[1]).toEqual({value: "/usr/bin/env clojure", scopes: ["source.clojure", "comment.line.shebang.clojure"]}); }); it("tokenizes strings", function() { const {tokens} = grammar.tokenizeLine('"foo bar"'); expect(tokens[0]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.begin.clojure"]}); expect(tokens[1]).toEqual({value: 'foo bar', scopes: ["source.clojure", "string.quoted.double.clojure"]}); - return expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.end.clojure"]}); + expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.end.clojure"]}); }); it("tokenizes character escape sequences", function() { const {tokens} = grammar.tokenizeLine('"\\n"'); expect(tokens[0]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.begin.clojure"]}); expect(tokens[1]).toEqual({value: '\\n', scopes: ["source.clojure", "string.quoted.double.clojure", "constant.character.escape.clojure"]}); - return expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.end.clojure"]}); + expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.quoted.double.clojure", "punctuation.definition.string.end.clojure"]}); }); it("tokenizes regexes", function() { const {tokens} = grammar.tokenizeLine('#"foo"'); expect(tokens[0]).toEqual({value: '#"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.begin.clojure"]}); expect(tokens[1]).toEqual({value: 'foo', scopes: ["source.clojure", "string.regexp.clojure"]}); - return expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.end.clojure"]}); + expect(tokens[2]).toEqual({value: '"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.end.clojure"]}); }); it("tokenizes backslash escape character in regexes", function() { @@ -69,14 +62,14 @@ describe("Clojure grammar", function() { expect(tokens[2]).toEqual({value: '"', scopes: ['source.clojure', 'string.regexp.clojure', "punctuation.definition.regexp.end.clojure"]}); expect(tokens[4]).toEqual({value: '"', scopes: ['source.clojure', 'string.quoted.double.clojure', 'punctuation.definition.string.begin.clojure']}); expect(tokens[5]).toEqual({value: "/", scopes: ['source.clojure', 'string.quoted.double.clojure']}); - return expect(tokens[6]).toEqual({value: '"', scopes: ['source.clojure', 'string.quoted.double.clojure', 'punctuation.definition.string.end.clojure']}); + expect(tokens[6]).toEqual({value: '"', scopes: ['source.clojure', 'string.quoted.double.clojure', 'punctuation.definition.string.end.clojure']}); }); it("tokenizes escaped double quote in regexes", function() { const {tokens} = grammar.tokenizeLine('#"\\""'); expect(tokens[0]).toEqual({value: '#"', scopes: ["source.clojure", "string.regexp.clojure", "punctuation.definition.regexp.begin.clojure"]}); expect(tokens[1]).toEqual({value: '\\"', scopes: ['source.clojure', 'string.regexp.clojure', 'constant.character.escape.clojure']}); - return expect(tokens[2]).toEqual({value: '"', scopes: ['source.clojure', 'string.regexp.clojure', "punctuation.definition.regexp.end.clojure"]}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.clojure', 'string.regexp.clojure', "punctuation.definition.regexp.end.clojure"]}); }); it("tokenizes numerics", function() { @@ -130,7 +123,7 @@ describe("Clojure grammar", function() { it("tokenizes nil", function() { const {tokens} = grammar.tokenizeLine("nil"); - return expect(tokens[0]).toEqual({value: "nil", scopes: ["source.clojure", "constant.language.nil.clojure"]}); + expect(tokens[0]).toEqual({value: "nil", scopes: ["source.clojure", "constant.language.nil.clojure"]}); }); it("tokenizes keywords", function() { @@ -155,7 +148,7 @@ describe("Clojure grammar", function() { // keywords can start with an uppercase non-ASCII letter ({tokens} = grammar.tokenizeLine("(def foo :Öπ)")); - return expect(tokens[5]).toEqual({value: ":Öπ", scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "constant.keyword.clojure"]}); + expect(tokens[5]).toEqual({value: ":Öπ", scopes: ["source.clojure", "meta.expression.clojure", "meta.definition.global.clojure", "constant.keyword.clojure"]}); }); it("tokenizes keyfns (keyword control)", function() { @@ -226,7 +219,7 @@ describe("Clojure grammar", function() { expect(tokens[1]).toEqual({value: ":foo", scopes: ["source.clojure", "meta.metadata.map.clojure", "constant.keyword.clojure"]}); expect(tokens[2]).toEqual({value: " ", scopes: ["source.clojure", "meta.metadata.map.clojure"]}); expect(tokens[3]).toEqual({value: "true", scopes: ["source.clojure", "meta.metadata.map.clojure", "constant.language.boolean.clojure"]}); - return expect(tokens[4]).toEqual({value: "}", scopes: ["source.clojure", "meta.metadata.map.clojure", "punctuation.section.metadata.map.end.trailing.clojure"]}); + expect(tokens[4]).toEqual({value: "}", scopes: ["source.clojure", "meta.metadata.map.clojure", "punctuation.section.metadata.map.end.trailing.clojure"]}); }); it("tokenizes functions", function() { @@ -240,7 +233,7 @@ describe("Clojure grammar", function() { //non-ASCII letters ({tokens} = grammar.tokenizeLine("(Öπ 2 20)")); - return expect(tokens[1]).toEqual({value: "Öπ", scopes: ["source.clojure", "meta.expression.clojure", "entity.name.function.clojure"]}); + expect(tokens[1]).toEqual({value: "Öπ", scopes: ["source.clojure", "meta.expression.clojure", "entity.name.function.clojure"]}); }); it("tokenizes vars", function() { @@ -251,7 +244,7 @@ describe("Clojure grammar", function() { // non-ASCII letters ({tokens} = grammar.tokenizeLine("(func #'Öπ)")); expect(tokens[2]).toEqual({value: " #", scopes: ["source.clojure", "meta.expression.clojure"]}); - return expect(tokens[3]).toEqual({value: "'Öπ", scopes: ["source.clojure", "meta.expression.clojure", "meta.var.clojure"]}); + expect(tokens[3]).toEqual({value: "'Öπ", scopes: ["source.clojure", "meta.expression.clojure", "meta.var.clojure"]}); }); it("tokenizes symbols", function() { @@ -264,7 +257,7 @@ describe("Clojure grammar", function() { // Should not be tokenized as a symbol ({tokens} = grammar.tokenizeLine("1foobar")); - return expect(tokens[0]).toEqual({value: "1", scopes: ["source.clojure", "constant.numeric.long.clojure"]}); + expect(tokens[0]).toEqual({value: "1", scopes: ["source.clojure", "constant.numeric.long.clojure"]}); }); it("tokenizes namespaces", function() { @@ -277,7 +270,7 @@ describe("Clojure grammar", function() { ({tokens} = grammar.tokenizeLine("Öπ/Åä")); expect(tokens[0]).toEqual({value: "Öπ", scopes: ["source.clojure", "meta.symbol.namespace.clojure"]}); expect(tokens[1]).toEqual({value: "/", scopes: ["source.clojure"]}); - return expect(tokens[2]).toEqual({value: "Åä", scopes: ["source.clojure", "meta.symbol.clojure"]}); + expect(tokens[2]).toEqual({value: "Åä", scopes: ["source.clojure", "meta.symbol.clojure"]}); }); const testMetaSection = function(metaScope, puncScope, startsWith, endsWith) { @@ -327,7 +320,7 @@ describe("Clojure grammar", function() { it("tokenizes quoted expressions", function() { testMetaSection("quoted-expression", "expression", "'(", ")"); - return testMetaSection("quoted-expression", "expression", "`(", ")"); + testMetaSection("quoted-expression", "expression", "`(", ")"); }); it("tokenizes vectors", () => testMetaSection("vector", "vector", "[", "]")); @@ -346,7 +339,7 @@ describe("Clojure grammar", function() { expect(tokens[5]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "meta.expression.clojure", "punctuation.section.expression.end.clojure"]}); expect(tokens[6]).toEqual({value: " ", scopes: ["source.clojure", "meta.expression.clojure"]}); expect(tokens[7]).toEqual({value: "baz", scopes: ["source.clojure", "meta.expression.clojure", "meta.symbol.clojure"]}); - return expect(tokens[8]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); + expect(tokens[8]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); }); it("tokenizes maps used as functions", function() { @@ -359,7 +352,7 @@ describe("Clojure grammar", function() { expect(tokens[5]).toEqual({value: "}", scopes: ["source.clojure", "meta.expression.clojure", "meta.map.clojure", "punctuation.section.map.end.clojure"]}); expect(tokens[6]).toEqual({value: " ", scopes: ["source.clojure", "meta.expression.clojure"]}); expect(tokens[7]).toEqual({value: ":foo", scopes: ["source.clojure", "meta.expression.clojure", "constant.keyword.clojure"]}); - return expect(tokens[8]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); + expect(tokens[8]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); }); it("tokenizes sets used in functions", function() { @@ -370,10 +363,10 @@ describe("Clojure grammar", function() { expect(tokens[3]).toEqual({value: " ", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure"]}); expect(tokens[4]).toEqual({value: ":bar", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "constant.keyword.clojure"]}); expect(tokens[5]).toEqual({value: "}", scopes: ["source.clojure", "meta.expression.clojure", "meta.set.clojure", "punctuation.section.set.end.trailing.clojure"]}); - return expect(tokens[6]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); + expect(tokens[6]).toEqual({value: ")", scopes: ["source.clojure", "meta.expression.clojure", "punctuation.section.expression.end.trailing.clojure"]}); }); - return describe("firstLineMatch", function() { + describe("firstLineMatch", function() { it("recognises interpreter directives", function() { let line; const valid = `\ @@ -457,7 +450,7 @@ describe("Clojure grammar", function() { })(); }); - return it("recognises Vim modelines", function() { + it("recognises Vim modelines", function() { let line; const valid = `\ vim: se filetype=clojure: From bf7b3280b310a66fc7284e8d71adf95256b11f77 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 18:05:56 -0700 Subject: [PATCH 05/18] Decaf `language-coffee-script` --- .../spec/coffee-script-literate-spec.coffee | 122 -- .../spec/coffee-script-literate-spec.js | 18 +- .../spec/coffee-script-spec.coffee | 1489 ----------------- .../spec/coffee-script-spec.js | 170 +- 4 files changed, 88 insertions(+), 1711 deletions(-) delete mode 100644 packages/language-coffee-script/spec/coffee-script-literate-spec.coffee delete mode 100644 packages/language-coffee-script/spec/coffee-script-spec.coffee diff --git a/packages/language-coffee-script/spec/coffee-script-literate-spec.coffee b/packages/language-coffee-script/spec/coffee-script-literate-spec.coffee deleted file mode 100644 index 511a027401..0000000000 --- a/packages/language-coffee-script/spec/coffee-script-literate-spec.coffee +++ /dev/null @@ -1,122 +0,0 @@ -describe "CoffeeScript (Literate) grammar", -> - grammar = null - - beforeEach -> - waitsForPromise -> - atom.packages.activatePackage("language-coffee-script") - - runs -> - grammar = atom.grammars.grammarForScopeName("source.litcoffee") - - it "parses the grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe "source.litcoffee" - - it "recognizes a code block after a list", -> - tokens = grammar.tokenizeLines ''' - 1. Example - 2. List - - 1 + 2 - ''' - expect(tokens[3][1]).toEqual value: "1", scopes: ["source.litcoffee", "markup.raw.block.markdown", "constant.numeric.decimal.coffee"] - - describe "firstLineMatch", -> - it "recognises interpreter directives", -> - valid = """ - #!/usr/local/bin/coffee --no-header --literate -w - #!/usr/local/bin/coffee -l - #!/usr/local/bin/env coffee --literate -w - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - #!/usr/local/bin/coffee --no-head -literate -w - #!/usr/local/bin/coffee --wl - #!/usr/local/bin/env coffee --illiterate -w=l - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - it "recognises Emacs modelines", -> - valid = """ - #-*- litcoffee -*- - #-*- mode: litcoffee -*- - /* -*-litcoffee-*- */ - // -*- litcoffee -*- - /* -*- mode:LITCOFFEE -*- */ - // -*- font:bar;mode:LitCoffee -*- - // -*- font:bar;mode:litcoffee;foo:bar; -*- - // -*-font:mode;mode:litcoffee-*- - // -*- foo:bar mode: litcoffee bar:baz -*- - " -*-foo:bar;mode:litcoffee;bar:foo-*- "; - " -*-font-mode:foo;mode:LITcofFEE;foo-bar:quux-*-" - "-*-font:x;foo:bar; mode : litCOFFEE; bar:foo;foooooo:baaaaar;fo:ba;-*-"; - "-*- font:x;foo : bar ; mode : LiTcOFFEe ; bar : foo ; foooooo:baaaaar;fo:ba-*-"; - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - /* --*litcoffee-*- */ - /* -*-- litcoffee -*- - /* -*- -- litcoffee -*- - /* -*- LITCOFFEE -;- -*- - // -*- itsLitCoffeeFam -*- - // -*- litcoffee; -*- - // -*- litcoffee-stuff -*- - /* -*- model:litcoffee -*- - /* -*- indent-mode:litcoffee -*- - // -*- font:mode;litcoffee -*- - // -*- mode: -*- litcoffee - // -*- mode: burnt-because-litcoffee -*- - // -*-font:mode;mode:litcoffee--*- - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - it "recognises Vim modelines", -> - valid = """ - vim: se filetype=litcoffee: - # vim: se ft=litcoffee: - # vim: set ft=LITCOFFEE: - # vim: set filetype=litcoffee: - # vim: ft=LITCOFFEE - # vim: syntax=litcoffee - # vim: se syntax=litcoffee: - # ex: syntax=litcoffee - # vim:ft=LitCoffee - # vim600: ft=litcoffee - # vim>600: set ft=litcoffee: - # vi:noai:sw=3 ts=6 ft=litcoffee - # vi::::::::::noai:::::::::::: ft=litcoffee - # vim:ts=4:sts=4:sw=4:noexpandtab:ft=LITCOFFEE - # vi:: noai : : : : sw =3 ts =6 ft =litCoffee - # vim: ts=4: pi sts=4: ft=litcoffee: noexpandtab: sw=4: - # vim: ts=4 sts=4: ft=litcoffee noexpandtab: - # vim:noexpandtab sts=4 ft=LitCOffEE ts=4 - # vim:noexpandtab:ft=litcoffee - # vim:ts=4:sts=4 ft=litcoffee:noexpandtab:\x20 - # vim:noexpandtab titlestring=hi\|there\\\\ ft=litcoffee ts=4 - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - ex: se filetype=litcoffee: - _vi: se filetype=litcoffee: - vi: se filetype=litcoffee - # vim set ft=illitcoffee - # vim: soft=litcoffee - # vim: clean-syntax=litcoffee: - # vim set ft=litcoffee: - # vim: setft=litcoffee: - # vim: se ft=litcoffee backupdir=tmp - # vim: set ft=LITCOFFEE set cmdheight=1 - # vim:noexpandtab sts:4 ft:litcoffee ts:4 - # vim:noexpandtab titlestring=hi\\|there\\ ft=litcoffee ts=4 - # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=litcoffee ts=4 - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() diff --git a/packages/language-coffee-script/spec/coffee-script-literate-spec.js b/packages/language-coffee-script/spec/coffee-script-literate-spec.js index b86aa34fb3..b86e162be0 100644 --- a/packages/language-coffee-script/spec/coffee-script-literate-spec.js +++ b/packages/language-coffee-script/spec/coffee-script-literate-spec.js @@ -1,22 +1,16 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS205: Consider reworking code to avoid use of IIFEs - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe("CoffeeScript (Literate) grammar", function() { let grammar = null; beforeEach(function() { waitsForPromise(() => atom.packages.activatePackage("language-coffee-script")); - return runs(() => grammar = atom.grammars.grammarForScopeName("source.litcoffee")); + runs(() => grammar = atom.grammars.grammarForScopeName("source.litcoffee")); }); it("parses the grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe("source.litcoffee"); + expect(grammar.scopeName).toBe("source.litcoffee"); }); it("recognizes a code block after a list", function() { @@ -27,10 +21,10 @@ describe("CoffeeScript (Literate) grammar", function() { 1 + 2\ ` ); - return expect(tokens[3][1]).toEqual({value: "1", scopes: ["source.litcoffee", "markup.raw.block.markdown", "constant.numeric.decimal.coffee"]}); + expect(tokens[3][1]).toEqual({value: "1", scopes: ["source.litcoffee", "markup.raw.block.markdown", "constant.numeric.decimal.coffee"]}); }); - return describe("firstLineMatch", function() { + describe("firstLineMatch", function() { it("recognises interpreter directives", function() { let line; const valid = `\ @@ -101,7 +95,7 @@ describe("CoffeeScript (Literate) grammar", function() { })(); }); - return it("recognises Vim modelines", function() { + it("recognises Vim modelines", function() { let line; const valid = `\ vim: se filetype=litcoffee: diff --git a/packages/language-coffee-script/spec/coffee-script-spec.coffee b/packages/language-coffee-script/spec/coffee-script-spec.coffee deleted file mode 100644 index 14940c89ae..0000000000 --- a/packages/language-coffee-script/spec/coffee-script-spec.coffee +++ /dev/null @@ -1,1489 +0,0 @@ -fs = require 'fs' -path = require 'path' - -describe "CoffeeScript grammar", -> - grammar = null - - beforeEach -> - waitsForPromise -> - atom.packages.activatePackage("language-coffee-script") - - runs -> - grammar = atom.grammars.grammarForScopeName("source.coffee") - - it "parses the grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe "source.coffee" - - it "tokenizes classes", -> - {tokens} = grammar.tokenizeLine("class Foo") - - expect(tokens[0]).toEqual value: "class", scopes: ["source.coffee", "meta.class.coffee", "storage.type.class.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.class.coffee"] - expect(tokens[2]).toEqual value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.name.type.class.coffee"] - - {tokens} = grammar.tokenizeLine("class_ Foo") - expect(tokens[0]).toEqual value: "class_", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - - {tokens} = grammar.tokenizeLine("_class Foo") - expect(tokens[0]).toEqual value: "_class", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - - {tokens} = grammar.tokenizeLine("[class Foo]") - expect(tokens[0]).toEqual value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"] - expect(tokens[1]).toEqual value: "class", scopes: ["source.coffee", "meta.class.coffee", "storage.type.class.coffee"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.coffee", "meta.class.coffee"] - expect(tokens[3]).toEqual value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.name.type.class.coffee"] - expect(tokens[4]).toEqual value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"] - - {tokens} = grammar.tokenizeLine("bar(class Foo)") - expect(tokens[0]).toEqual value: "bar", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[1]).toEqual value: "(", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "punctuation.definition.arguments.begin.bracket.round.coffee"] - expect(tokens[2]).toEqual value: "class", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee", "storage.type.class.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee"] - expect(tokens[4]).toEqual value: "Foo", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee", "entity.name.type.class.coffee"] - expect(tokens[5]).toEqual value: ")", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "punctuation.definition.arguments.end.bracket.round.coffee"] - - it "tokenizes named subclasses", -> - {tokens} = grammar.tokenizeLine("class Foo extends Bar") - - expect(tokens[0]).toEqual value: "class", scopes: ["source.coffee", "meta.class.coffee", "storage.type.class.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.class.coffee"] - expect(tokens[2]).toEqual value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.name.type.class.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee", "meta.class.coffee"] - expect(tokens[4]).toEqual value: "extends", scopes: ["source.coffee", "meta.class.coffee", "keyword.control.inheritance.coffee"] - expect(tokens[5]).toEqual value: " ", scopes: ["source.coffee", "meta.class.coffee"] - expect(tokens[6]).toEqual value: "Bar", scopes: ["source.coffee", "meta.class.coffee", "entity.other.inherited-class.coffee"] - - it "tokenizes anonymous subclasses", -> - {tokens} = grammar.tokenizeLine("class extends Foo") - - expect(tokens[0]).toEqual value: "class", scopes: ["source.coffee", "meta.class.coffee", "storage.type.class.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.class.coffee"] - expect(tokens[2]).toEqual value: "extends", scopes: ["source.coffee", "meta.class.coffee", "keyword.control.inheritance.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee", "meta.class.coffee"] - expect(tokens[4]).toEqual value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.other.inherited-class.coffee"] - - it "tokenizes instantiated anonymous classes", -> - {tokens} = grammar.tokenizeLine("new class") - - expect(tokens[0]).toEqual value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"] - expect(tokens[2]).toEqual value: "class", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "storage.type.class.coffee"] - - it "tokenizes instantiated named classes", -> - {tokens} = grammar.tokenizeLine("new class Foo") - - expect(tokens[0]).toEqual value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"] - expect(tokens[2]).toEqual value: "class", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "storage.type.class.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"] - expect(tokens[4]).toEqual value: "Foo", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"] - - {tokens} = grammar.tokenizeLine("new Foo") - - expect(tokens[0]).toEqual value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"] - expect(tokens[2]).toEqual value: "Foo", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"] - - it "tokenizes class names that start with `class` correctly", -> - {tokens} = grammar.tokenizeLine("new classTest") - - expect(tokens[0]).toEqual value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"] - expect(tokens[2]).toEqual value: "classTest", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"] - - it "tokenizes comments", -> - {tokens} = grammar.tokenizeLine("# I am a comment") - - expect(tokens[0]).toEqual value: "#", scopes: ["source.coffee", "comment.line.number-sign.coffee", "punctuation.definition.comment.coffee"] - expect(tokens[1]).toEqual value: " I am a comment", scopes: ["source.coffee", "comment.line.number-sign.coffee"] - - {tokens} = grammar.tokenizeLine("\#{Comment}") - - expect(tokens[0]).toEqual value: "#", scopes: ["source.coffee", "comment.line.number-sign.coffee", "punctuation.definition.comment.coffee"] - expect(tokens[1]).toEqual value: "{Comment}", scopes: ["source.coffee", "comment.line.number-sign.coffee"] - - it "tokenizes block comments", -> - lines = grammar.tokenizeLines """ - ### I am a block comment - Very blocky - Until here - ### - """ - expect(lines[0][0]).toEqual value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee'] - expect(lines[0][1]).toEqual value: ' I am a block comment', scopes: ['source.coffee', 'comment.block.coffee'] - expect(lines[2][0]).toEqual value: 'Until here', scopes: ['source.coffee', 'comment.block.coffee'] - expect(lines[3][0]).toEqual value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee'] - - {tokens} = grammar.tokenizeLine "identity = ###::### (value ###: T ###) ###: T ### ->" - expect(tokens[0]).toEqual value: 'identity', scopes: ['source.coffee', 'variable.assignment.coffee'] - expect(tokens[4]).toEqual value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee'] - expect(tokens[5]).toEqual value: '::', scopes: ['source.coffee', 'comment.block.coffee'] - expect(tokens[6]).toEqual value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee'] - expect(tokens[9]).toEqual value: 'value ', scopes: ['source.coffee'] # TODO: These scopes are incorrect and should be fixed - expect(tokens[10]).toEqual value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee'] - expect(tokens[11]).toEqual value: ': T ', scopes: ['source.coffee', 'comment.block.coffee'] - expect(tokens[12]).toEqual value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee'] - expect(tokens[14]).toEqual value: ' ', scopes: ['source.coffee'] # TODO: These scopes are incorrect and should be fixed - expect(tokens[15]).toEqual value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee'] - expect(tokens[16]).toEqual value: ': T ', scopes: ['source.coffee', 'comment.block.coffee'] - expect(tokens[17]).toEqual value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee'] - expect(tokens[19]).toEqual value: '->', scopes: ['source.coffee', 'meta.function.inline.coffee', 'storage.type.function.coffee'] - - it "tokenizes annotations in block comments", -> - lines = grammar.tokenizeLines """ - ### - @foo - food - @bar - bart - """ - - expect(lines[1][0]).toEqual value: ' ', scopes: ["source.coffee", "comment.block.coffee"] - expect(lines[1][1]).toEqual value: '@foo', scopes: ["source.coffee", "comment.block.coffee", "storage.type.annotation.coffee"] - expect(lines[2][0]).toEqual value: '@bar', scopes: ["source.coffee", "comment.block.coffee", "storage.type.annotation.coffee"] - - describe "numbers", -> - it "tokenizes hexadecimals", -> - {tokens} = grammar.tokenizeLine('0x1D306') - expect(tokens[0]).toEqual value: '0x1D306', scopes: ['source.coffee', 'constant.numeric.hex.coffee'] - - {tokens} = grammar.tokenizeLine('0X1D306') - expect(tokens[0]).toEqual value: '0X1D306', scopes: ['source.coffee', 'constant.numeric.hex.coffee'] - - it "tokenizes binary literals", -> - {tokens} = grammar.tokenizeLine('0b011101110111010001100110') - expect(tokens[0]).toEqual value: '0b011101110111010001100110', scopes: ['source.coffee', 'constant.numeric.binary.coffee'] - - {tokens} = grammar.tokenizeLine('0B011101110111010001100110') - expect(tokens[0]).toEqual value: '0B011101110111010001100110', scopes: ['source.coffee', 'constant.numeric.binary.coffee'] - - it "tokenizes octal literals", -> - {tokens} = grammar.tokenizeLine('0o1411') - expect(tokens[0]).toEqual value: '0o1411', scopes: ['source.coffee', 'constant.numeric.octal.coffee'] - - {tokens} = grammar.tokenizeLine('0O1411') - expect(tokens[0]).toEqual value: '0O1411', scopes: ['source.coffee', 'constant.numeric.octal.coffee'] - - {tokens} = grammar.tokenizeLine('0010') - expect(tokens[0]).toEqual value: '0010', scopes: ['source.coffee', 'constant.numeric.octal.coffee'] - - it "tokenizes decimals", -> - {tokens} = grammar.tokenizeLine('1234') - expect(tokens[0]).toEqual value: '1234', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - - {tokens} = grammar.tokenizeLine('5e-10') - expect(tokens[0]).toEqual value: '5e-10', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - - {tokens} = grammar.tokenizeLine('5E+5') - expect(tokens[0]).toEqual value: '5E+5', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - - {tokens} = grammar.tokenizeLine('9.') - expect(tokens[0]).toEqual value: '9', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee'] - - {tokens} = grammar.tokenizeLine('.9') - expect(tokens[0]).toEqual value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee'] - expect(tokens[1]).toEqual value: '9', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - - {tokens} = grammar.tokenizeLine('9.9') - expect(tokens[0]).toEqual value: '9', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee'] - expect(tokens[2]).toEqual value: '9', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - - {tokens} = grammar.tokenizeLine('.1e-23') - expect(tokens[0]).toEqual value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee'] - expect(tokens[1]).toEqual value: '1e-23', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - - {tokens} = grammar.tokenizeLine('1.E3') - expect(tokens[0]).toEqual value: '1', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee'] - expect(tokens[2]).toEqual value: 'E3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - - it "does not tokenize numbers that are part of a variable", -> - {tokens} = grammar.tokenizeLine('hi$1') - expect(tokens[0]).toEqual value: 'hi$1', scopes: ['source.coffee'] - - {tokens} = grammar.tokenizeLine('hi_1') - expect(tokens[0]).toEqual value: 'hi_1', scopes: ['source.coffee'] - - it "tokenizes variable assignments", -> - {tokens} = grammar.tokenizeLine("something = b") - expect(tokens[0]).toEqual value: "something", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("something : b") - expect(tokens[0]).toEqual value: "something", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: ":", scopes: ["source.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("a and= b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "and=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - # Should NOT be tokenized as and= - {tokens} = grammar.tokenizeLine("operand=true") - expect(tokens[0]).toEqual value: "operand", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[1]).toEqual value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"] - - {tokens} = grammar.tokenizeLine("a or= b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "or=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - # Should NOT be tokenized as or= - {tokens} = grammar.tokenizeLine("editor=false") - expect(tokens[0]).toEqual value: "editor", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[1]).toEqual value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"] - - {tokens} = grammar.tokenizeLine("a -= b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "-=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("a += b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "+=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("a /= b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "/=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("a &= b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "&=", scopes: ["source.coffee", "keyword.operator.assignment.compound.bitwise.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("a %= b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "%=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("a *= b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "*=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("a ?= b") - expect(tokens[0]).toEqual value: "a", scopes: ["source.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "?=", scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("a == b") - expect(tokens[0]).toEqual value: "a ", scopes: ["source.coffee"] - expect(tokens[1]).toEqual value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - expect(tokens[2]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("false == b") - expect(tokens[0]).toEqual value: "false", scopes: ["source.coffee", "constant.language.boolean.false.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("true == b") - expect(tokens[0]).toEqual value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("null == b") - expect(tokens[0]).toEqual value: "null", scopes: ["source.coffee", "constant.language.null.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("this == b") - expect(tokens[0]).toEqual value: "this", scopes: ["source.coffee", "variable.language.this.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - it "tokenizes compound operators properly", -> - assignmentOperators = ["and=", "or=", "&&=", "||=", "/=", "*=", "%=", "+=", "-="] - bitwiseOperators = ["<<=", ">>=", ">>>=", "&=", "|=", "^="] - comparisonOperators = ["==", "!=", "<=", ">="] - - for assignmentOperator in assignmentOperators - {tokens} = grammar.tokenizeLine(assignmentOperator) - expect(tokens[0]).toEqual value: assignmentOperator, scopes: ["source.coffee", "keyword.operator.assignment.compound.coffee"] - - for bitwiseOperator in bitwiseOperators - {tokens} = grammar.tokenizeLine(bitwiseOperator) - expect(tokens[0]).toEqual value: bitwiseOperator, scopes: ["source.coffee", "keyword.operator.assignment.compound.bitwise.coffee"] - - for comparisonOperator in comparisonOperators - {tokens} = grammar.tokenizeLine(comparisonOperator) - expect(tokens[0]).toEqual value: comparisonOperator, scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - - it "tokenizes operators properly", -> - logicalOperators = ["!", "&&", "||", "and", "or", "not"] - bitwiseOperators = ["^", "~", "&", "|"] - comparisonOperators = ["<", ">", "is", "isnt"] - decrementOperators = ["--"] - incrementOperators = ["++"] - splatOperators = ["..."] - existentialOperators = ["?"] - operators = ["%", "*", "/", "-", "+"] - keywords = ["delete", "instanceof", "new", "typeof"] - - for logicalOperator in logicalOperators - {tokens} = grammar.tokenizeLine(logicalOperator) - expect(tokens[0]).toEqual value: logicalOperator, scopes: ["source.coffee", "keyword.operator.logical.coffee"] - - for bitwiseOperator in bitwiseOperators - {tokens} = grammar.tokenizeLine(bitwiseOperator) - expect(tokens[0]).toEqual value: bitwiseOperator, scopes: ["source.coffee", "keyword.operator.bitwise.coffee"] - - for comparisonOperator in comparisonOperators - {tokens} = grammar.tokenizeLine(comparisonOperator) - expect(tokens[0]).toEqual value: comparisonOperator, scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - - for decrementOperator in decrementOperators - {tokens} = grammar.tokenizeLine(decrementOperator) - expect(tokens[0]).toEqual value: decrementOperator, scopes: ["source.coffee", "keyword.operator.decrement.coffee"] - - for incrementOperator in incrementOperators - {tokens} = grammar.tokenizeLine(incrementOperator) - expect(tokens[0]).toEqual value: incrementOperator, scopes: ["source.coffee", "keyword.operator.increment.coffee"] - - for splatOperator in splatOperators - {tokens} = grammar.tokenizeLine(splatOperator) - expect(tokens[0]).toEqual value: splatOperator, scopes: ["source.coffee", "keyword.operator.splat.coffee"] - - for existentialOperator in existentialOperators - {tokens} = grammar.tokenizeLine(existentialOperator) - expect(tokens[0]).toEqual value: existentialOperator, scopes: ["source.coffee", "keyword.operator.existential.coffee"] - - for operator in operators - {tokens} = grammar.tokenizeLine(operator) - expect(tokens[0]).toEqual value: operator, scopes: ["source.coffee", "keyword.operator.coffee"] - - for keyword in keywords - {tokens} = grammar.tokenizeLine(keyword) - expect(tokens[0]).toEqual value: keyword, scopes: ["source.coffee", "keyword.operator.#{keyword}.coffee"] - - it "does not tokenize non-operators as operators", -> - notOperators = ["(/=", "-->", "=>", "->"] - - for notOperator in notOperators - {tokens} = grammar.tokenizeLine(notOperator) - expect(tokens[0]).not.toEqual value: notOperator, scopes: ["source.coffee", "keyword.operator.coffee"] - - describe "properties", -> - it "tokenizes properties", -> - {tokens} = grammar.tokenizeLine('obj.property') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: 'property', scopes: ['source.coffee', 'variable.other.property.coffee'] - - {tokens} = grammar.tokenizeLine('obj.property instanceof Object') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: 'property', scopes: ['source.coffee', 'variable.other.property.coffee'] - - {tokens} = grammar.tokenizeLine('obj.property.property') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: 'property', scopes: ['source.coffee', 'variable.other.object.property.coffee'] - - {tokens} = grammar.tokenizeLine('obj.Property') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: 'Property', scopes: ['source.coffee', 'variable.other.property.coffee'] - - {tokens} = grammar.tokenizeLine('obj.prop1?.prop2?') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: 'prop1', scopes: ['source.coffee', 'variable.other.object.property.coffee'] - expect(tokens[3]).toEqual value: '?', scopes: ['source.coffee', 'keyword.operator.existential.coffee'] - expect(tokens[4]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[5]).toEqual value: 'prop2', scopes: ['source.coffee', 'variable.other.property.coffee'] - expect(tokens[6]).toEqual value: '?', scopes: ['source.coffee', 'keyword.operator.existential.coffee'] - - {tokens} = grammar.tokenizeLine('obj.$abc$') - expect(tokens[2]).toEqual value: '$abc$', scopes: ['source.coffee', 'variable.other.property.coffee'] - - {tokens} = grammar.tokenizeLine('obj.$$') - expect(tokens[2]).toEqual value: '$$', scopes: ['source.coffee', 'variable.other.property.coffee'] - - {tokens} = grammar.tokenizeLine('a().b') - expect(tokens[2]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - expect(tokens[3]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[4]).toEqual value: 'b', scopes: ['source.coffee', 'variable.other.property.coffee'] - - {tokens} = grammar.tokenizeLine('a.123illegal') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: '123illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee'] - - it "tokenizes constant properties", -> - {tokens} = grammar.tokenizeLine('obj.MY_CONSTANT') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: 'MY_CONSTANT', scopes: ['source.coffee', 'constant.other.property.coffee'] - - {tokens} = grammar.tokenizeLine('obj.MY_CONSTANT.prop') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: 'MY_CONSTANT', scopes: ['source.coffee', 'constant.other.object.property.coffee'] - - {tokens} = grammar.tokenizeLine('a.C') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[2]).toEqual value: 'C', scopes: ['source.coffee', 'constant.other.property.coffee'] - - it "tokenizes objects, methods, and properties using :: prototype syntax", -> - {tokens} = grammar.tokenizeLine("Foo::") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::true") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "true", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::on") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "on", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::yes") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "yes", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::false") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "false", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::off") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "off", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::no") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "no", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::null") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "null", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::extends") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "extends", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo :: something :: else") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[4]).toEqual value: "something", scopes: ["source.coffee", "variable.other.object.property.coffee"] - expect(tokens[5]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[6]).toEqual value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[7]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[8]).toEqual value: "else", scopes: ["source.coffee", "variable.other.property.coffee"] - - {tokens} = grammar.tokenizeLine("Foo::toString()") - expect(tokens[0]).toEqual value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"] - expect(tokens[1]).toEqual value: "::", scopes: ["source.coffee", "meta.method-call.coffee", "keyword.operator.prototype.coffee"] - expect(tokens[2]).toEqual value: "toString", scopes: ["source.coffee", "meta.method-call.coffee", "support.function.coffee"] - - describe "variables", -> - it "tokenizes 'this'", -> - {tokens} = grammar.tokenizeLine('this') - expect(tokens[0]).toEqual value: 'this', scopes: ['source.coffee', 'variable.language.this.coffee'] - - {tokens} = grammar.tokenizeLine('this.obj.prototype = new El()') - expect(tokens[0]).toEqual value: 'this', scopes: ['source.coffee', 'variable.language.this.coffee'] - - {tokens} = grammar.tokenizeLine('$this') - expect(tokens[0]).toEqual value: '$this', scopes: ['source.coffee'] - - {tokens} = grammar.tokenizeLine('this$') - expect(tokens[0]).toEqual value: 'this$', scopes: ['source.coffee'] - - it "tokenizes 'super'", -> - {tokens} = grammar.tokenizeLine('super') - expect(tokens[0]).toEqual value: 'super', scopes: ['source.coffee', 'variable.language.super.coffee'] - - it "tokenizes 'arguments'", -> - {tokens} = grammar.tokenizeLine('arguments') - expect(tokens[0]).toEqual value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee'] - - {tokens} = grammar.tokenizeLine('arguments[0]') - expect(tokens[0]).toEqual value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee'] - - {tokens} = grammar.tokenizeLine('arguments.length') - expect(tokens[0]).toEqual value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee'] - - it "tokenizes illegal identifiers", -> - {tokens} = grammar.tokenizeLine('0illegal') - expect(tokens[0]).toEqual value: '0illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee'] - - {tokens} = grammar.tokenizeLine('123illegal') - expect(tokens[0]).toEqual value: '123illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee'] - - {tokens} = grammar.tokenizeLine('123$illegal') - expect(tokens[0]).toEqual value: '123$illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee'] - - describe "objects", -> - it "tokenizes them", -> - {tokens} = grammar.tokenizeLine('obj.prop') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - - {tokens} = grammar.tokenizeLine('$abc$.prop') - expect(tokens[0]).toEqual value: '$abc$', scopes: ['source.coffee', 'variable.other.object.coffee'] - - {tokens} = grammar.tokenizeLine('$$.prop') - expect(tokens[0]).toEqual value: '$$', scopes: ['source.coffee', 'variable.other.object.coffee'] - - {tokens} = grammar.tokenizeLine('obj?.prop') - expect(tokens[0]).toEqual value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.coffee', 'keyword.operator.existential.coffee'] - - it "tokenizes illegal objects", -> - {tokens} = grammar.tokenizeLine('1.prop') - expect(tokens[0]).toEqual value: '1', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee'] - - {tokens} = grammar.tokenizeLine('123.prop') - expect(tokens[0]).toEqual value: '123', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee'] - - {tokens} = grammar.tokenizeLine('123a.prop') - expect(tokens[0]).toEqual value: '123a', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee'] - - describe "arrays", -> - it "tokenizes basic arrays", -> - {tokens} = grammar.tokenizeLine('[a, "b", 3]') - expect(tokens[0]).toEqual value: '[', scopes: ['source.coffee', 'punctuation.definition.array.begin.bracket.square.coffee'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.coffee'] - expect(tokens[2]).toEqual value: ',', scopes: ['source.coffee', 'punctuation.separator.delimiter.coffee'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.coffee'] - expect(tokens[9]).toEqual value: '3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[10]).toEqual value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee'] - - it "tokenizes inclusive and exclusive slices", -> - {tokens} = grammar.tokenizeLine('[a..3]') - expect(tokens[0]).toEqual value: '[', scopes: ['source.coffee', 'punctuation.definition.array.begin.bracket.square.coffee'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.coffee'] - expect(tokens[2]).toEqual value: '..', scopes: ['source.coffee', 'keyword.operator.slice.inclusive.coffee'] - expect(tokens[3]).toEqual value: '3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[4]).toEqual value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee'] - - {tokens} = grammar.tokenizeLine('[3...b]') - expect(tokens[0]).toEqual value: '[', scopes: ['source.coffee', 'punctuation.definition.array.begin.bracket.square.coffee'] - expect(tokens[1]).toEqual value: '3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[2]).toEqual value: '...', scopes: ['source.coffee', 'keyword.operator.slice.exclusive.coffee'] - expect(tokens[3]).toEqual value: 'b', scopes: ['source.coffee'] - expect(tokens[4]).toEqual value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee'] - - it "verifies that regular expressions have explicit count modifiers", -> - source = fs.readFileSync(path.resolve(__dirname, '..', 'grammars', 'coffeescript.cson'), 'utf8') - expect(source.search /{,/).toEqual -1 - - source = fs.readFileSync(path.resolve(__dirname, '..', 'grammars', 'coffeescript (literate).cson'), 'utf8') - expect(source.search /{,/).toEqual -1 - - it "tokenizes embedded JavaScript", -> - waitsForPromise -> - atom.packages.activatePackage("language-javascript") - - runs -> - {tokens} = grammar.tokenizeLine("`;`") - expect(tokens[0]).toEqual value: "`", scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: ";", scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "punctuation.terminator.statement.js"] - expect(tokens[2]).toEqual value: "`", scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.end.coffee"] - - lines = grammar.tokenizeLines """ - `var a = 1;` - a = 2 - """ - expect(lines[0][0]).toEqual value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.begin.coffee"] - expect(lines[0][1]).toEqual value: 'var', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "storage.type.var.js"] - expect(lines[0][6]).toEqual value: ';', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "punctuation.terminator.statement.js"] - expect(lines[0][7]).toEqual value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.end.coffee"] - expect(lines[1][0]).toEqual value: 'a', scopes: ["source.coffee", "variable.assignment.coffee"] - - {tokens} = grammar.tokenizeLine("`// comment` a = 2") - expect(tokens[0]).toEqual value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: '//', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "comment.line.double-slash.js", "punctuation.definition.comment.js"] - expect(tokens[2]).toEqual value: ' comment', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "comment.line.double-slash.js"] - expect(tokens[3]).toEqual value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.end.coffee"] - expect(tokens[5]).toEqual value: 'a', scopes: ["source.coffee", "variable.assignment.coffee"] - - describe "function calls", -> - it "tokenizes function calls", -> - {tokens} = grammar.tokenizeLine('functionCall()') - expect(tokens[0]).toEqual value: 'functionCall', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[2]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - - {tokens} = grammar.tokenizeLine('functionCall(arg1, "test", {a: 123})') - expect(tokens[0]).toEqual value: 'functionCall', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[2]).toEqual value: 'arg1', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee'] - expect(tokens[3]).toEqual value: ',', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.delimiter.coffee'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[6]).toEqual value: 'test', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee'] - expect(tokens[8]).toEqual value: ',', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.delimiter.coffee'] - expect(tokens[10]).toEqual value: '{', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.curly.coffee'] - expect(tokens[11]).toEqual value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'variable.assignment.coffee'] - expect(tokens[12]).toEqual value: ':', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'keyword.operator.assignment.coffee'] - expect(tokens[14]).toEqual value: '123', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[15]).toEqual value: '}', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.curly.coffee'] - expect(tokens[16]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - - {tokens} = grammar.tokenizeLine('functionCall((123).toString())') - expect(tokens[1]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.round.coffee'] - expect(tokens[3]).toEqual value: '123', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[4]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.round.coffee'] - expect(tokens[9]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - - {tokens} = grammar.tokenizeLine('$abc$()') - expect(tokens[0]).toEqual value: '$abc$', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('$$()') - expect(tokens[0]).toEqual value: '$$', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('ABC()') - expect(tokens[0]).toEqual value: 'ABC', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('$ABC$()') - expect(tokens[0]).toEqual value: '$ABC$', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('@$()') - expect(tokens[0]).toEqual value: '@', scopes: ['source.coffee', 'meta.function-call.coffee', 'variable.other.readwrite.instance.coffee'] - expect(tokens[1]).toEqual value: '$', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('functionCall arg1, "test", {a: 123}') - expect(tokens[0]).toEqual value: 'functionCall', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[2]).toEqual value: 'arg1', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee'] - expect(tokens[3]).toEqual value: ',', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.delimiter.coffee'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[6]).toEqual value: 'test', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee'] - expect(tokens[8]).toEqual value: ',', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.delimiter.coffee'] - expect(tokens[10]).toEqual value: '{', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.curly.coffee'] - expect(tokens[11]).toEqual value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'variable.assignment.coffee'] - expect(tokens[12]).toEqual value: ':', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'keyword.operator.assignment.coffee'] - expect(tokens[14]).toEqual value: '123', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[15]).toEqual value: '}', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.brace.curly.coffee'] - - {tokens} = grammar.tokenizeLine("foo bar") - expect(tokens[0]).toEqual value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.function-call.coffee"] - expect(tokens[2]).toEqual value: "bar", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"] - - {tokens} = grammar.tokenizeLine("foo not food") - expect(tokens[0]).toEqual value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.function-call.coffee"] - expect(tokens[2]).toEqual value: "not", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "keyword.operator.logical.coffee"] - expect(tokens[3]).toEqual value: " food", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"] - - {tokens} = grammar.tokenizeLine("eat food for food in foods") - expect(tokens[0]).toEqual value: "eat", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[2]).toEqual value: "food", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"] - expect(tokens[4]).toEqual value: "for", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[5]).toEqual value: " food ", scopes: ["source.coffee"] - expect(tokens[6]).toEqual value: "in", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[7]).toEqual value: " foods", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("(eat food for food in get foods)") - expect(tokens[0]).toEqual value: "(", scopes: ["source.coffee", "meta.brace.round.coffee"] - expect(tokens[1]).toEqual value: "eat", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[3]).toEqual value: "food", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"] - expect(tokens[5]).toEqual value: "for", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[6]).toEqual value: " food ", scopes: ["source.coffee"] - expect(tokens[7]).toEqual value: "in", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[9]).toEqual value: "get", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[11]).toEqual value: "foods", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"] - expect(tokens[12]).toEqual value: ")", scopes: ["source.coffee", "meta.brace.round.coffee"] - - {tokens} = grammar.tokenizeLine("[eat food]") - expect(tokens[0]).toEqual value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"] - expect(tokens[1]).toEqual value: "eat", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[3]).toEqual value: "food", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"] - expect(tokens[4]).toEqual value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"] - - {tokens} = grammar.tokenizeLine("foo @bar") - expect(tokens[0]).toEqual value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[2]).toEqual value: "@bar", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "variable.other.readwrite.instance.coffee"] - - {tokens} = grammar.tokenizeLine("@foo bar") - expect(tokens[0]).toEqual value: "@", scopes: ["source.coffee", "meta.function-call.coffee", "variable.other.readwrite.instance.coffee"] - expect(tokens[1]).toEqual value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[3]).toEqual value: "bar", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"] - - {tokens} = grammar.tokenizeLine("foo baz, @bar") - expect(tokens[0]).toEqual value: "foo", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[2]).toEqual value: "baz", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee"] - expect(tokens[3]).toEqual value: ",", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[5]).toEqual value: "@bar", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "variable.other.readwrite.instance.coffee"] - - {tokens} = grammar.tokenizeLine("$ @$") - expect(tokens[0]).toEqual value: "$", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"] - expect(tokens[2]).toEqual value: "@$", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "variable.other.readwrite.instance.coffee"] - - it "tokenizes function calls when they are arguments", -> - {tokens} = grammar.tokenizeLine('a(b(c))') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[4]).toEqual value: 'c', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee'] - expect(tokens[5]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - - {tokens} = grammar.tokenizeLine('a b c') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[4]).toEqual value: 'c', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee'] - - it "tokenizes illegal function calls", -> - {tokens} = grammar.tokenizeLine('0illegal()') - expect(tokens[0]).toEqual value: '0illegal', scopes: ['source.coffee', 'meta.function-call.coffee', 'invalid.illegal.identifier.coffee'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[2]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - - it "tokenizes illegal arguments", -> - {tokens} = grammar.tokenizeLine('a(1a)') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[2]).toEqual value: '1a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee'] - expect(tokens[3]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - - {tokens} = grammar.tokenizeLine('a(123a)') - expect(tokens[2]).toEqual value: '123a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee'] - - {tokens} = grammar.tokenizeLine('a(1.prop)') - expect(tokens[2]).toEqual value: '1', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee'] - expect(tokens[3]).toEqual value: '.', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.separator.property.period.coffee'] - expect(tokens[4]).toEqual value: 'prop', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'variable.other.property.coffee'] - - {tokens} = grammar.tokenizeLine('a 1a') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[2]).toEqual value: '1a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee'] - - it "tokenizes function declaration as an argument", -> - {tokens} = grammar.tokenizeLine('a((p) -> return p )') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.begin.bracket.round.coffee'] - expect(tokens[3]).toEqual value: 'p', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'variable.parameter.function.coffee'] - expect(tokens[4]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.end.bracket.round.coffee'] - expect(tokens[8]).toEqual value: 'return', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'keyword.control.coffee'] - expect(tokens[9]).toEqual value: ' p ', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee'] - expect(tokens[10]).toEqual value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - - it "does not tokenize booleans as function calls", -> - {tokens} = grammar.tokenizeLine("false unless true") - expect(tokens[0]).toEqual value: "false", scopes: ["source.coffee", "constant.language.boolean.false.coffee"] - expect(tokens[2]).toEqual value: "unless", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[4]).toEqual value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"] - - {tokens} = grammar.tokenizeLine("true if false") - expect(tokens[0]).toEqual value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"] - expect(tokens[2]).toEqual value: "if", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[4]).toEqual value: "false", scopes: ["source.coffee", "constant.language.boolean.false.coffee"] - - it "does not tokenize comparison operators as function calls", -> - {tokens} = grammar.tokenizeLine("if a is b") - expect(tokens[1]).toEqual value: " a ", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: "is", scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - expect(tokens[3]).toEqual value: " b", scopes: ["source.coffee"] - - describe "functions", -> - it "tokenizes regular functions", -> - {tokens} = grammar.tokenizeLine("foo = -> 1") - expect(tokens[0]).toEqual value: "foo", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[2]).toEqual value: "=", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[4]).toEqual value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"] - expect(tokens[5]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[6]).toEqual value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"] - - {tokens} = grammar.tokenizeLine("@foo = -> 1") - expect(tokens[0]).toEqual value: "@", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee", "variable.other.readwrite.instance.coffee"] - expect(tokens[1]).toEqual value: "foo", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"] - expect(tokens[3]).toEqual value: "=", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"] - - {tokens} = grammar.tokenizeLine("$ = => 1") - expect(tokens[0]).toEqual value: "$", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"] - expect(tokens[2]).toEqual value: "=", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"] - - {tokens} = grammar.tokenizeLine("foo: -> 1") - expect(tokens[0]).toEqual value: "foo", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"] - expect(tokens[1]).toEqual value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[3]).toEqual value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[5]).toEqual value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"] - - {tokens} = grammar.tokenizeLine("'quoted': (a) => true") - expect(tokens[0]).toEqual value: "'", scopes: ["source.coffee", "meta.function.coffee", "string.quoted.single.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: "quoted", scopes: ["source.coffee", "meta.function.coffee", "string.quoted.single.coffee", "entity.name.function.coffee"] - expect(tokens[2]).toEqual value: "'", scopes: ["source.coffee", "meta.function.coffee", "string.quoted.single.coffee", "punctuation.definition.string.end.coffee"] - expect(tokens[3]).toEqual value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[5]).toEqual value: "(", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"] - expect(tokens[6]).toEqual value: "a", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[7]).toEqual value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[9]).toEqual value: "=>", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"] - expect(tokens[10]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[11]).toEqual value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"] - - {tokens} = grammar.tokenizeLine('"quoted": (a) -> true') - expect(tokens[0]).toEqual value: '"', scopes: ["source.coffee", "meta.function.coffee", "string.quoted.double.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: "quoted", scopes: ["source.coffee", "meta.function.coffee", "string.quoted.double.coffee", "entity.name.function.coffee"] - expect(tokens[2]).toEqual value: '"', scopes: ["source.coffee", "meta.function.coffee", "string.quoted.double.coffee", "punctuation.definition.string.end.coffee"] - expect(tokens[3]).toEqual value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[5]).toEqual value: "(", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"] - expect(tokens[6]).toEqual value: "a", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[7]).toEqual value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[9]).toEqual value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"] - expect(tokens[10]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[11]).toEqual value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"] - - {tokens} = grammar.tokenizeLine("hello: (a) -> 1") - expect(tokens[0]).toEqual value: "hello", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"] - expect(tokens[1]).toEqual value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[3]).toEqual value: "(", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"] - expect(tokens[4]).toEqual value: "a", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[5]).toEqual value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"] - expect(tokens[6]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee"] - expect(tokens[7]).toEqual value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"] - expect(tokens[9]).toEqual value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"] - - {tokens} = grammar.tokenizeLine("hello: (a, b, {c, d}, e = 'test', f = 3, g = -> 4) -> 1") - expect(tokens[0]).toEqual value: "hello", scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"] - expect(tokens[1]).toEqual value: ":", scopes: ["source.coffee", "meta.function.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[3]).toEqual value: "(", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"] - expect(tokens[4]).toEqual value: "a", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[5]).toEqual value: ",", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[6]).toEqual value: " ", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee"] - expect(tokens[7]).toEqual value: "b", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[8]).toEqual value: ",", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[10]).toEqual value: "{", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "meta.brace.curly.coffee"] - expect(tokens[11]).toEqual value: "c", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee"] - expect(tokens[12]).toEqual value: ",", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[13]).toEqual value: " d", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee"] - expect(tokens[14]).toEqual value: "}", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "meta.brace.curly.coffee"] - expect(tokens[17]).toEqual value: "e", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[19]).toEqual value: "=", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[21]).toEqual value: "'", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "string.quoted.single.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[24]).toEqual value: ",", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[26]).toEqual value: "f", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[30]).toEqual value: "3", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "constant.numeric.decimal.coffee"] - expect(tokens[33]).toEqual value: "g", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[35]).toEqual value: "=", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[37]).toEqual value: "->", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"] - expect(tokens[40]).toEqual value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"] - expect(tokens[42]).toEqual value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"] - - it "tokenizes inline functions", -> - {tokens} = grammar.tokenizeLine("-> true") - expect(tokens[0]).toEqual value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine(" -> true") - expect(tokens[0]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[1]).toEqual value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("->true") - expect(tokens[0]).toEqual value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"] - - {tokens} = grammar.tokenizeLine("(arg) -> true") - expect(tokens[0]).toEqual value: "(", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"] - expect(tokens[1]).toEqual value: "arg", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[2]).toEqual value: ")", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee", "meta.function.inline.coffee"] - expect(tokens[4]).toEqual value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"] - expect(tokens[5]).toEqual value: " ", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("(arg1, arg2) -> true") - expect(tokens[0]).toEqual value: "(", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"] - expect(tokens[1]).toEqual value: "arg1", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[2]).toEqual value: ",", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"] - expect(tokens[4]).toEqual value: "arg2", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[5]).toEqual value: ")", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"] - expect(tokens[6]).toEqual value: " ", scopes: ["source.coffee", "meta.function.inline.coffee"] - expect(tokens[7]).toEqual value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("( arg1, arg2 )-> true") - expect(tokens[0]).toEqual value: "(", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.begin.bracket.round.coffee"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"] - expect(tokens[2]).toEqual value: "arg1", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[3]).toEqual value: ",", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"] - expect(tokens[5]).toEqual value: "arg2", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "variable.parameter.function.coffee"] - expect(tokens[6]).toEqual value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"] - expect(tokens[7]).toEqual value: ")", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"] - expect(tokens[8]).toEqual value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"] - expect(tokens[9]).toEqual value: " ", scopes: ["source.coffee"] - - describe "method calls", -> - it "tokenizes method calls", -> - {tokens} = grammar.tokenizeLine('a.b(1+1)') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - expect(tokens[4]).toEqual value: '1', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[5]).toEqual value: '+', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'keyword.operator.coffee'] - expect(tokens[6]).toEqual value: '1', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee'] - - {tokens} = grammar.tokenizeLine('a . b(1+1)') - expect(tokens[2]).toEqual value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee'] - expect(tokens[4]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee'] - - {tokens} = grammar.tokenizeLine('a.$abc$()') - expect(tokens[2]).toEqual value: '$abc$', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('a.$$()') - expect(tokens[2]).toEqual value: '$$', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('a.b c') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee'] - expect(tokens[4]).toEqual value: 'c', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee'] - - {tokens} = grammar.tokenizeLine('(a.b c)') - expect(tokens[0]).toEqual value: '(', scopes: ['source.coffee', 'meta.brace.round.coffee'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[2]).toEqual value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee'] - expect(tokens[3]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee'] - expect(tokens[5]).toEqual value: 'c', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.coffee', 'meta.brace.round.coffee'] - - {tokens} = grammar.tokenizeLine("[a.b c]") - expect(tokens[0]).toEqual value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[2]).toEqual value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee'] - expect(tokens[3]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee'] - expect(tokens[5]).toEqual value: 'c', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee'] - expect(tokens[6]).toEqual value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"] - - {tokens} = grammar.tokenizeLine('a.b not c') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee'] - expect(tokens[4]).toEqual value: 'not', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'keyword.operator.logical.coffee'] - expect(tokens[5]).toEqual value: ' c', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee'] - - {tokens} = grammar.tokenizeLine('a.b 1+1') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee'] - expect(tokens[4]).toEqual value: '1', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee'] - expect(tokens[5]).toEqual value: '+', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'keyword.operator.coffee'] - expect(tokens[6]).toEqual value: '1', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'constant.numeric.decimal.coffee'] - - {tokens} = grammar.tokenizeLine('a.b @') - expect(tokens[2]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[4]).toEqual value: '@', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'variable.other.readwrite.instance.coffee'] - - {tokens} = grammar.tokenizeLine('a.$abc$ "q"') - expect(tokens[2]).toEqual value: '$abc$', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('a.$$ 4') - expect(tokens[2]).toEqual value: '$$', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - - {tokens} = grammar.tokenizeLine('a.b @$') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee'] - expect(tokens[4]).toEqual value: '@$', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'variable.other.readwrite.instance.coffee'] - - describe "destructuring assignments", -> - it "tokenizes object and array destructuring", -> - {tokens} = grammar.tokenizeLine("{something} = hi") - expect(tokens[0]).toEqual value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"] - expect(tokens[1]).toEqual value: "something", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[4]).toEqual value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[5]).toEqual value: " hi", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("[x, y] = browserWindow.getPosition()") - expect(tokens[0]).toEqual value: "[", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.begin.bracket.square.coffee"] - expect(tokens[1]).toEqual value: "x", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "variable.assignment.coffee"] - expect(tokens[2]).toEqual value: ",", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee"] - expect(tokens[4]).toEqual value: "y", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "variable.assignment.coffee"] - expect(tokens[5]).toEqual value: "]", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.end.bracket.square.coffee"] - expect(tokens[6]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[7]).toEqual value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.coffee"] - - {tokens} = grammar.tokenizeLine("{'} ='}") # Make sure this *isn't* tokenized as a destructuring assignment - expect(tokens[0]).not.toEqual value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"] - expect(tokens[0]).toEqual value: "{", scopes: ["source.coffee", "meta.brace.curly.coffee"] - - it "tokenizes nested destructuring assignments", -> - {tokens} = grammar.tokenizeLine("{poet: {name, address: [street, city]}} = futurists") - expect(tokens[0]).toEqual value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"] - expect(tokens[4]).toEqual value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"] - expect(tokens[11]).toEqual value: "[", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.begin.bracket.square.coffee"] - expect(tokens[16]).toEqual value: "]", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.end.bracket.square.coffee"] - expect(tokens[17]).toEqual value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"] - expect(tokens[18]).toEqual value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"] - expect(tokens[19]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[20]).toEqual value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"] - - it "tokenizes multiple nested destructuring assignments", -> - {tokens} = grammar.tokenizeLine("{start: {row: startRow}, end: {row: endRow}} = range") - expect(tokens[0]).toEqual value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"] - expect(tokens[4]).toEqual value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"] - expect(tokens[9]).toEqual value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"] - expect(tokens[15]).toEqual value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"] - expect(tokens[20]).toEqual value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"] - expect(tokens[21]).toEqual value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"] - expect(tokens[22]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[23]).toEqual value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"] - - it "doesn't tokenize nested brackets as destructuring assignments", -> - {tokens} = grammar.tokenizeLine("[Point(0, 1), [Point(0, 0), Point(0, 1)]]") - expect(tokens[0]).not.toEqual value: "[", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.begin.bracket.square.coffee"] - expect(tokens[0]).toEqual value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"] - - it "tokenizes inline constant followed by unless statement correctly", -> - {tokens} = grammar.tokenizeLine("return 0 unless true") - expect(tokens[0]).toEqual value: "return", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[2]).toEqual value: "0", scopes: ["source.coffee", "constant.numeric.decimal.coffee"] - expect(tokens[4]).toEqual value: "unless", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[6]).toEqual value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"] - - describe "for loops", -> - it "tokenizes for-in loops", -> - {tokens} = grammar.tokenizeLine("for food in foods") - expect(tokens[0]).toEqual value: "for", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[1]).toEqual value: " food ", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: "in", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[3]).toEqual value: " foods", scopes: ["source.coffee"] - - it "tokenizes for-of loops", -> - {tokens} = grammar.tokenizeLine("for food, type of foods") - expect(tokens[0]).toEqual value: "for", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[1]).toEqual value: " food", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: ",", scopes: ["source.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[3]).toEqual value: " type ", scopes: ["source.coffee"] - expect(tokens[4]).toEqual value: "of", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[5]).toEqual value: " foods", scopes: ["source.coffee"] - - it "tokenizes loops using arrays", -> - {tokens} = grammar.tokenizeLine("for food in ['broccoli', 'spinach', 'chocolate']") - expect(tokens[0]).toEqual value: "for", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[1]).toEqual value: " food ", scopes: ["source.coffee"] - expect(tokens[2]).toEqual value: "in", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[4]).toEqual value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"] - expect(tokens[18]).toEqual value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"] - - it "tokenizes loops using the optional `when` keyword", -> - {tokens} = grammar.tokenizeLine("for food in foods when food isnt chocolate") - expect(tokens[0]).toEqual value: "for", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[3]).toEqual value: " foods ", scopes: ["source.coffee"] - expect(tokens[4]).toEqual value: "when", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[5]).toEqual value: " food ", scopes: ["source.coffee"] - expect(tokens[6]).toEqual value: "isnt", scopes: ["source.coffee", "keyword.operator.comparison.coffee"] - expect(tokens[7]).toEqual value: " chocolate", scopes: ["source.coffee"] - - it "tokenizes loops using the optional `by` keyword", -> - {tokens} = grammar.tokenizeLine("for food in foods by -1") - expect(tokens[0]).toEqual value: "for", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[3]).toEqual value: " foods ", scopes: ["source.coffee"] - expect(tokens[4]).toEqual value: "by", scopes: ["source.coffee", "keyword.control.coffee"] - expect(tokens[5]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[6]).toEqual value: "-", scopes: ["source.coffee", "keyword.operator.coffee"] - expect(tokens[7]).toEqual value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"] - - describe "regular expressions", -> - beforeEach -> - waitsForPromise -> - atom.packages.activatePackage("language-javascript") # Provides the regexp subgrammar - - it "tokenizes regular expressions", -> - {tokens} = grammar.tokenizeLine("/test/") - expect(tokens[0]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: "test", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[2]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - - {tokens} = grammar.tokenizeLine("/{'}/") - expect(tokens[0]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[2]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - - {tokens} = grammar.tokenizeLine("foo + /test/") - expect(tokens[0]).toEqual value: "foo ", scopes: ["source.coffee"] - expect(tokens[1]).toEqual value: "+", scopes: ["source.coffee", "keyword.operator.coffee"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[3]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[4]).toEqual value: "test", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[5]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - - it "tokenizes regular expressions containing spaces", -> - {tokens} = grammar.tokenizeLine("/ te st /") - expect(tokens[0]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: " te st ", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[2]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - - it "tokenizes regular expressions containing escaped forward slashes", -> - {tokens} = grammar.tokenizeLine("/test\\//") - expect(tokens[0]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: "test", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[2]).toEqual value: "\\/", scopes: ["source.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"] - expect(tokens[3]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - - {tokens} = grammar.tokenizeLine("/one\\/two!\\/three/") - expect(tokens[0]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: "one", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[2]).toEqual value: "\\/", scopes: ["source.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"] - expect(tokens[3]).toEqual value: "two!", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[4]).toEqual value: "\\/", scopes: ["source.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"] - expect(tokens[5]).toEqual value: "three", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[6]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - - it "tokenizes regular expressions inside arrays", -> - {tokens} = grammar.tokenizeLine("[/test/]") - expect(tokens[0]).toEqual value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"] - expect(tokens[1]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[2]).toEqual value: "test", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[3]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - expect(tokens[4]).toEqual value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"] - - {tokens} = grammar.tokenizeLine("[1, /test/]") - expect(tokens[0]).toEqual value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"] - expect(tokens[1]).toEqual value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"] - expect(tokens[2]).toEqual value: ",", scopes: ["source.coffee", "punctuation.separator.delimiter.coffee"] - expect(tokens[3]).toEqual value: " ", scopes: ["source.coffee"] - expect(tokens[4]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[5]).toEqual value: "test", scopes: ["source.coffee", "string.regexp.coffee"] - expect(tokens[6]).toEqual value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - expect(tokens[7]).toEqual value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"] - - it "does not tokenize multiple division as regex", -> - # https://github.com/atom/language-coffee-script/issues/112 - {tokens} = grammar.tokenizeLine("a / b + c / d") - expect(tokens[1]).toEqual value: "/", scopes: ["source.coffee", "keyword.operator.coffee"] - expect(tokens[2]).toEqual value: " b ", scopes: ["source.coffee"] - expect(tokens[5]).toEqual value: "/", scopes: ["source.coffee", "keyword.operator.coffee"] - - {tokens} = grammar.tokenizeLine("a / 2 / (3)") - expect(tokens[1]).toEqual value: "/", scopes: ["source.coffee", "keyword.operator.coffee"] - expect(tokens[3]).toEqual value: "2", scopes: ["source.coffee", "constant.numeric.decimal.coffee"] - expect(tokens[5]).toEqual value: "/", scopes: ["source.coffee", "keyword.operator.coffee"] - - it "does not tokenize comments with URLs in them as regex", -> - # Disclaimer: This does not fix when comments contain only slashes, such as `a / something # comment /` - {tokens} = grammar.tokenizeLine("canvas.width/2 # https://github.com/atom/language-coffee-script/issues/112") - expect(tokens[3]).toEqual value: "/", scopes: ["source.coffee", "keyword.operator.coffee"] - expect(tokens[6]).toEqual value: "#", scopes: ["source.coffee", "comment.line.number-sign.coffee", "punctuation.definition.comment.coffee"] - expect(tokens[7]).toEqual value: " https://github.com/atom/language-coffee-script/issues/112", scopes: ["source.coffee", "comment.line.number-sign.coffee"] - - it "stops tokenizing regex at the first non-escaped forwards slash", -> - {tokens} = grammar.tokenizeLine("path.replace(/\\\\/g, '/')") - expect(tokens[4]).toEqual value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[6]).toEqual value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - expect(tokens[11]).toEqual value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.quoted.single.coffee"] - - {tokens} = grammar.tokenizeLine("path.replace(/\\\\\\//g, '/')") - expect(tokens[4]).toEqual value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"] - expect(tokens[6]).toEqual value: "\\/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"] - expect(tokens[7]).toEqual value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"] - expect(tokens[12]).toEqual value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.quoted.single.coffee"] - - it "tokenises multi-line regular expressions", -> - {tokens} = grammar.tokenizeLine('/// (XYZ) ///') - expect(tokens[0]).toEqual value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'meta.group.regexp', 'punctuation.definition.group.regexp'] - expect(tokens[3]).toEqual value: 'XYZ', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'meta.group.regexp'] - expect(tokens[4]).toEqual value: ')', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'meta.group.regexp', 'punctuation.definition.group.regexp'] - expect(tokens[6]).toEqual value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.end.coffee'] - - lines = grammar.tokenizeLines """ - /// - XYZ // - /~/ - /// - """ - expect(lines[0][0]).toEqual value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.begin.coffee'] - expect(lines[1][0]).toEqual value: 'XYZ //', scopes: ['source.coffee', 'string.regexp.multiline.coffee'] - expect(lines[2][0]).toEqual value: '/~/', scopes: ['source.coffee', 'string.regexp.multiline.coffee'] - expect(lines[3][0]).toEqual value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.end.coffee'] - - describe "here-docs", -> - it "tokenises single-quoted here-docs", -> - {tokens} = grammar.tokenizeLine "'''XYZ'''" - expect(tokens[0]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[1]).toEqual value: 'XYZ', scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee'] - expect(tokens[2]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.end.coffee'] - - lines = grammar.tokenizeLines """ - ''' - 'ABC' - XYZ '' - ''' - """ - expect(lines[0][0]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.begin.coffee'] - expect(lines[1][0]).toEqual value: "'ABC'", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee'] - expect(lines[2][0]).toEqual value: "XYZ ''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee'] - expect(lines[3][0]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.end.coffee'] - - it "tokenises double-quoted here-docs", -> - {tokens} = grammar.tokenizeLine "'''XYZ'''" - expect(tokens[0]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[1]).toEqual value: 'XYZ', scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee'] - expect(tokens[2]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.end.coffee'] - - lines = grammar.tokenizeLines ''' - """ - "ABC" - XYZ "" - """ - ''' - expect(lines[0][0]).toEqual value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.begin.coffee'] - expect(lines[1][0]).toEqual value: '"ABC"', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee'] - expect(lines[2][0]).toEqual value: 'XYZ ""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee'] - expect(lines[3][0]).toEqual value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.end.coffee'] - - describe "escape sequences in strings", -> - it "tokenises leading backslashes in double-quoted strings", -> - {tokens} = grammar.tokenizeLine('"a\\\\b\\\\\\\\c"') - expect(tokens[0]).toEqual value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.coffee', 'string.quoted.double.coffee'] - expect(tokens[2]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[3]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[4]).toEqual value: 'b', scopes: ['source.coffee', 'string.quoted.double.coffee'] - expect(tokens[5]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[6]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[7]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[8]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[9]).toEqual value: 'c', scopes: ['source.coffee', 'string.quoted.double.coffee'] - expect(tokens[10]).toEqual value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee'] - - {tokens} = grammar.tokenizeLine('"\\a\\t\\a\\b"') - expect(tokens[0]).toEqual value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[1]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[2]).toEqual value: 'a', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[3]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[4]).toEqual value: 't', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[5]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[6]).toEqual value: 'a', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[7]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[8]).toEqual value: 'b', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee'] - - it "tokenises leading backslashes in single-quoted strings", -> - {tokens} = grammar.tokenizeLine("'a\\\\b\\\\\\\\c'") - expect(tokens[0]).toEqual value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.coffee', 'string.quoted.single.coffee'] - expect(tokens[2]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[3]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[4]).toEqual value: 'b', scopes: ['source.coffee', 'string.quoted.single.coffee'] - expect(tokens[5]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[6]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[7]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[8]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[9]).toEqual value: 'c', scopes: ['source.coffee', 'string.quoted.single.coffee'] - expect(tokens[10]).toEqual value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee'] - - {tokens} = grammar.tokenizeLine("'\\a\\t\\a\\b'") - expect(tokens[0]).toEqual value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[1]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[2]).toEqual value: 'a', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[3]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[4]).toEqual value: 't', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[5]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[6]).toEqual value: 'a', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[7]).toEqual value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee'] - expect(tokens[8]).toEqual value: 'b', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee'] - expect(tokens[9]).toEqual value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee'] - - describe "jsx", -> - it "tokenises HTML tags", -> - {tokens} = grammar.tokenizeLine("
") - expect(tokens[0]).toEqual value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee'] - expect(tokens[1]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ] - expect(tokens[2]).toEqual value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ] - expect(tokens[3]).toEqual value: '', scopes: ['source.coffee', 'meta.tag.coffee' ] - - {tokens} = grammar.tokenizeLine("
") - expect(tokens[0]).toEqual value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee'] - expect(tokens[1]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ] - expect(tokens[2]).toEqual value: '/>', scopes: ['source.coffee', 'meta.tag.coffee' ] - - it "tokenises HTML tags with attributes", -> - {tokens} = grammar.tokenizeLine("
") - expect(tokens[0]).toEqual value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee'] - expect(tokens[1]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ] - expect(tokens[3]).toEqual value: 'class', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ] - expect(tokens[4]).toEqual value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ] - expect(tokens[5]).toEqual value: '\'', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.begin.coffee' ] - expect(tokens[6]).toEqual value: 'myclass', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee' ] - expect(tokens[7]).toEqual value: '\'', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee' ] - expect(tokens[8]).toEqual value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ] - expect(tokens[9]).toEqual value: 'id', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ] - expect(tokens[10]).toEqual value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ] - expect(tokens[11]).toEqual value: '"', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee' ] - expect(tokens[12]).toEqual value: 'myid', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee' ] - expect(tokens[13]).toEqual value: '"', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee' ] - expect(tokens[14]).toEqual value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ] - - it "tokenises HTML tags with attributes that have expressions", -> - {tokens} = grammar.tokenizeLine("
@handleClick(e)}>") - expect(tokens[0]).toEqual value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee'] - expect(tokens[1]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ] - expect(tokens[3]).toEqual value: 'on-click', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ] - expect(tokens[4]).toEqual value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ] - expect(tokens[5]).toEqual value: '{', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.brace.curly.coffee'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.begin.bracket.round.coffee' ] - expect(tokens[7]).toEqual value: 'e', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'variable.parameter.function.coffee' ] - expect(tokens[8]).toEqual value: ')', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.end.bracket.round.coffee' ] - expect(tokens[9]).toEqual value: '->', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'storage.type.function.coffee' ] - expect(tokens[10]).toEqual value: '@', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'variable.other.readwrite.instance.coffee' ] - expect(tokens[11]).toEqual value: 'handleClick', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee' ] - expect(tokens[12]).toEqual value: '(', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee' ] - expect(tokens[13]).toEqual value: 'e', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee' ] - expect(tokens[14]).toEqual value: ')', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee' ] - expect(tokens[15]).toEqual value: '}', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.brace.curly.coffee'] - expect(tokens[16]).toEqual value: '>', scopes: ['source.coffee', 'meta.tag.coffee'] - - describe "firstLineMatch", -> - it "recognises interpreter directives", -> - valid = """ - #!/usr/sbin/coffee foo - #!/usr/bin/coffee foo=bar/ - #!/usr/sbin/coffee - #!/usr/sbin/coffee foo bar baz - #!/usr/bin/coffee perl - #!/usr/bin/coffee bin/perl - #!/usr/bin/coffee - #!/bin/coffee - #!/usr/bin/coffee --script=usr/bin - #! /usr/bin/env A=003 B=149 C=150 D=xzd E=base64 F=tar G=gz H=head I=tail coffee - #!\t/usr/bin/env --foo=bar coffee --quu=quux - #! /usr/bin/coffee - #!/usr/bin/env coffee - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - \x20#!/usr/sbin/coffee - \t#!/usr/sbin/coffee - #!/usr/bin/env-coffee/node-env/ - #!/usr/bin/env-coffee - #! /usr/bincoffee - #!\t/usr/bin/env --coffee=bar - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - it "recognises Emacs modelines", -> - valid = """ - #-*- coffee -*- - #-*- mode: Coffee -*- - /* -*-coffee-*- */ - // -*- Coffee -*- - /* -*- mode:Coffee -*- */ - // -*- font:bar;mode:Coffee -*- - // -*- font:bar;mode:Coffee;foo:bar; -*- - // -*-font:mode;mode:COFFEE-*- - // -*- foo:bar mode: coffee bar:baz -*- - " -*-foo:bar;mode:cOFFEE;bar:foo-*- "; - " -*-font-mode:foo;mode:coFFeE;foo-bar:quux-*-" - "-*-font:x;foo:bar; mode : Coffee; bar:foo;foooooo:baaaaar;fo:ba;-*-"; - "-*- font:x;foo : bar ; mode : Coffee ; bar : foo ; foooooo:baaaaar;fo:ba-*-"; - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - /* --*coffee-*- */ - /* -*-- coffee -*- - /* -*- -- Coffee -*- - /* -*- Coffee -;- -*- - // -*- freeCoffee -*- - // -*- Coffee; -*- - // -*- coffee-sugar -*- - /* -*- model:coffee -*- - /* -*- indent-mode:coffee -*- - // -*- font:mode;Coffee -*- - // -*- mode: -*- Coffee - // -*- mode: jfc-give-me-coffee -*- - // -*-font:mode;mode:coffee--*- - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - it "recognises Vim modelines", -> - valid = """ - vim: se filetype=coffee: - # vim: se ft=coffee: - # vim: set ft=COFFEE: - # vim: set filetype=CoffEE: - # vim: ft=CoffEE - # vim: syntax=CoffEE - # vim: se syntax=CoffEE: - # ex: syntax=CoffEE - # vim:ft=coffee - # vim600: ft=coffee - # vim>600: set ft=coffee: - # vi:noai:sw=3 ts=6 ft=coffee - # vi::::::::::noai:::::::::::: ft=COFFEE - # vim:ts=4:sts=4:sw=4:noexpandtab:ft=cOfFeE - # vi:: noai : : : : sw =3 ts =6 ft =coFFEE - # vim: ts=4: pi sts=4: ft=cofFeE: noexpandtab: sw=4: - # vim: ts=4 sts=4: ft=coffee noexpandtab: - # vim:noexpandtab sts=4 ft=coffEE ts=4 - # vim:noexpandtab:ft=cOFFEe - # vim:ts=4:sts=4 ft=cofFeE:noexpandtab:\x20 - # vim:noexpandtab titlestring=hi\|there\\\\ ft=cOFFEe ts=4 - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - ex: se filetype=coffee: - _vi: se filetype=coffee: - vi: se filetype=coffee - # vim set ft=coffee - # vim: soft=coffee - # vim: clean-syntax=coffee: - # vim set ft=coffee: - # vim: setft=coffee: - # vim: se ft=coffee backupdir=tmp - # vim: set ft=coffee set cmdheight=1 - # vim:noexpandtab sts:4 ft:coffee ts:4 - # vim:noexpandtab titlestring=hi\\|there\\ ft=coffee ts=4 - # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=coffee ts=4 - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() diff --git a/packages/language-coffee-script/spec/coffee-script-spec.js b/packages/language-coffee-script/spec/coffee-script-spec.js index 41a7a9c8ed..953d97c5c5 100644 --- a/packages/language-coffee-script/spec/coffee-script-spec.js +++ b/packages/language-coffee-script/spec/coffee-script-spec.js @@ -1,10 +1,4 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS205: Consider reworking code to avoid use of IIFEs - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + const fs = require('fs'); const path = require('path'); @@ -14,12 +8,12 @@ describe("CoffeeScript grammar", function() { beforeEach(function() { waitsForPromise(() => atom.packages.activatePackage("language-coffee-script")); - return runs(() => grammar = atom.grammars.grammarForScopeName("source.coffee")); + runs(() => grammar = atom.grammars.grammarForScopeName("source.coffee")); }); it("parses the grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe("source.coffee"); + expect(grammar.scopeName).toBe("source.coffee"); }); it("tokenizes classes", function() { @@ -48,7 +42,7 @@ describe("CoffeeScript grammar", function() { expect(tokens[2]).toEqual({value: "class", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee", "storage.type.class.coffee"]}); expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee"]}); expect(tokens[4]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "meta.class.coffee", "entity.name.type.class.coffee"]}); - return expect(tokens[5]).toEqual({value: ")", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "punctuation.definition.arguments.end.bracket.round.coffee"]}); + expect(tokens[5]).toEqual({value: ")", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "punctuation.definition.arguments.end.bracket.round.coffee"]}); }); it("tokenizes named subclasses", function() { @@ -60,7 +54,7 @@ describe("CoffeeScript grammar", function() { expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); expect(tokens[4]).toEqual({value: "extends", scopes: ["source.coffee", "meta.class.coffee", "keyword.control.inheritance.coffee"]}); expect(tokens[5]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); - return expect(tokens[6]).toEqual({value: "Bar", scopes: ["source.coffee", "meta.class.coffee", "entity.other.inherited-class.coffee"]}); + expect(tokens[6]).toEqual({value: "Bar", scopes: ["source.coffee", "meta.class.coffee", "entity.other.inherited-class.coffee"]}); }); it("tokenizes anonymous subclasses", function() { @@ -70,7 +64,7 @@ describe("CoffeeScript grammar", function() { expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); expect(tokens[2]).toEqual({value: "extends", scopes: ["source.coffee", "meta.class.coffee", "keyword.control.inheritance.coffee"]}); expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.coffee"]}); - return expect(tokens[4]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.other.inherited-class.coffee"]}); + expect(tokens[4]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.coffee", "entity.other.inherited-class.coffee"]}); }); it("tokenizes instantiated anonymous classes", function() { @@ -78,7 +72,7 @@ describe("CoffeeScript grammar", function() { expect(tokens[0]).toEqual({value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"]}); expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"]}); - return expect(tokens[2]).toEqual({value: "class", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "storage.type.class.coffee"]}); + expect(tokens[2]).toEqual({value: "class", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "storage.type.class.coffee"]}); }); it("tokenizes instantiated named classes", function() { @@ -94,14 +88,14 @@ describe("CoffeeScript grammar", function() { expect(tokens[0]).toEqual({value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"]}); expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee", "meta.class.instance.constructor.coffee"]}); - return expect(tokens[2]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"]}); + expect(tokens[2]).toEqual({value: "Foo", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"]}); }); it("tokenizes class names that start with `class` correctly", function() { const {tokens} = grammar.tokenizeLine("new classTest"); expect(tokens[0]).toEqual({value: "new", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "keyword.operator.new.coffee"]}); - return expect(tokens[2]).toEqual({value: "classTest", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"]}); + expect(tokens[2]).toEqual({value: "classTest", scopes: ["source.coffee", "meta.class.instance.constructor.coffee", "entity.name.type.instance.coffee"]}); }); it("tokenizes comments", function() { @@ -113,7 +107,7 @@ describe("CoffeeScript grammar", function() { ({tokens} = grammar.tokenizeLine("\#{Comment}")); expect(tokens[0]).toEqual({value: "#", scopes: ["source.coffee", "comment.line.number-sign.coffee", "punctuation.definition.comment.coffee"]}); - return expect(tokens[1]).toEqual({value: "{Comment}", scopes: ["source.coffee", "comment.line.number-sign.coffee"]}); + expect(tokens[1]).toEqual({value: "{Comment}", scopes: ["source.coffee", "comment.line.number-sign.coffee"]}); }); it("tokenizes block comments", function() { @@ -142,7 +136,7 @@ Until here expect(tokens[15]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); expect(tokens[16]).toEqual({value: ': T ', scopes: ['source.coffee', 'comment.block.coffee']}); expect(tokens[17]).toEqual({value: '###', scopes: ['source.coffee', 'comment.block.coffee', 'punctuation.definition.comment.coffee']}); - return expect(tokens[19]).toEqual({value: '->', scopes: ['source.coffee', 'meta.function.inline.coffee', 'storage.type.function.coffee']}); + expect(tokens[19]).toEqual({value: '->', scopes: ['source.coffee', 'meta.function.inline.coffee', 'storage.type.function.coffee']}); }); it("tokenizes annotations in block comments", function() { @@ -155,7 +149,7 @@ Until here expect(lines[1][0]).toEqual({value: ' ', scopes: ["source.coffee", "comment.block.coffee"]}); expect(lines[1][1]).toEqual({value: '@foo', scopes: ["source.coffee", "comment.block.coffee", "storage.type.annotation.coffee"]}); - return expect(lines[2][0]).toEqual({value: '@bar', scopes: ["source.coffee", "comment.block.coffee", "storage.type.annotation.coffee"]}); + expect(lines[2][0]).toEqual({value: '@bar', scopes: ["source.coffee", "comment.block.coffee", "storage.type.annotation.coffee"]}); }); describe("numbers", function() { @@ -164,7 +158,7 @@ Until here expect(tokens[0]).toEqual({value: '0x1D306', scopes: ['source.coffee', 'constant.numeric.hex.coffee']}); ({tokens} = grammar.tokenizeLine('0X1D306')); - return expect(tokens[0]).toEqual({value: '0X1D306', scopes: ['source.coffee', 'constant.numeric.hex.coffee']}); + expect(tokens[0]).toEqual({value: '0X1D306', scopes: ['source.coffee', 'constant.numeric.hex.coffee']}); }); it("tokenizes binary literals", function() { @@ -172,7 +166,7 @@ Until here expect(tokens[0]).toEqual({value: '0b011101110111010001100110', scopes: ['source.coffee', 'constant.numeric.binary.coffee']}); ({tokens} = grammar.tokenizeLine('0B011101110111010001100110')); - return expect(tokens[0]).toEqual({value: '0B011101110111010001100110', scopes: ['source.coffee', 'constant.numeric.binary.coffee']}); + expect(tokens[0]).toEqual({value: '0B011101110111010001100110', scopes: ['source.coffee', 'constant.numeric.binary.coffee']}); }); it("tokenizes octal literals", function() { @@ -183,7 +177,7 @@ Until here expect(tokens[0]).toEqual({value: '0O1411', scopes: ['source.coffee', 'constant.numeric.octal.coffee']}); ({tokens} = grammar.tokenizeLine('0010')); - return expect(tokens[0]).toEqual({value: '0010', scopes: ['source.coffee', 'constant.numeric.octal.coffee']}); + expect(tokens[0]).toEqual({value: '0010', scopes: ['source.coffee', 'constant.numeric.octal.coffee']}); }); it("tokenizes decimals", function() { @@ -216,15 +210,15 @@ Until here ({tokens} = grammar.tokenizeLine('1.E3')); expect(tokens[0]).toEqual({value: '1', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'constant.numeric.decimal.coffee', 'punctuation.separator.decimal.period.coffee']}); - return expect(tokens[2]).toEqual({value: 'E3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); + expect(tokens[2]).toEqual({value: 'E3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); }); - return it("does not tokenize numbers that are part of a variable", function() { + it("does not tokenize numbers that are part of a variable", function() { let {tokens} = grammar.tokenizeLine('hi$1'); expect(tokens[0]).toEqual({value: 'hi$1', scopes: ['source.coffee']}); ({tokens} = grammar.tokenizeLine('hi_1')); - return expect(tokens[0]).toEqual({value: 'hi_1', scopes: ['source.coffee']}); + expect(tokens[0]).toEqual({value: 'hi_1', scopes: ['source.coffee']}); }); }); @@ -321,7 +315,7 @@ Until here expect(tokens[0]).toEqual({value: "this", scopes: ["source.coffee", "variable.language.this.coffee"]}); expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee"]}); expect(tokens[2]).toEqual({value: "==", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); - return expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); }); it("tokenizes compound operators properly", function() { @@ -470,7 +464,7 @@ Until here ({tokens} = grammar.tokenizeLine('a.123illegal')); expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee']}); expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); - return expect(tokens[2]).toEqual({value: '123illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + expect(tokens[2]).toEqual({value: '123illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); }); it("tokenizes constant properties", function() { @@ -487,10 +481,10 @@ Until here ({tokens} = grammar.tokenizeLine('a.C')); expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'variable.other.object.coffee']}); expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'punctuation.separator.property.period.coffee']}); - return expect(tokens[2]).toEqual({value: 'C', scopes: ['source.coffee', 'constant.other.property.coffee']}); + expect(tokens[2]).toEqual({value: 'C', scopes: ['source.coffee', 'constant.other.property.coffee']}); }); - return it("tokenizes objects, methods, and properties using :: prototype syntax", function() { + it("tokenizes objects, methods, and properties using :: prototype syntax", function() { let {tokens} = grammar.tokenizeLine("Foo::"); expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "keyword.operator.prototype.coffee"]}); @@ -549,7 +543,7 @@ Until here ({tokens} = grammar.tokenizeLine("Foo::toString()")); expect(tokens[0]).toEqual({value: "Foo", scopes: ["source.coffee", "variable.other.object.coffee"]}); expect(tokens[1]).toEqual({value: "::", scopes: ["source.coffee", "meta.method-call.coffee", "keyword.operator.prototype.coffee"]}); - return expect(tokens[2]).toEqual({value: "toString", scopes: ["source.coffee", "meta.method-call.coffee", "support.function.coffee"]}); + expect(tokens[2]).toEqual({value: "toString", scopes: ["source.coffee", "meta.method-call.coffee", "support.function.coffee"]}); }); }); @@ -565,12 +559,12 @@ Until here expect(tokens[0]).toEqual({value: '$this', scopes: ['source.coffee']}); ({tokens} = grammar.tokenizeLine('this$')); - return expect(tokens[0]).toEqual({value: 'this$', scopes: ['source.coffee']}); + expect(tokens[0]).toEqual({value: 'this$', scopes: ['source.coffee']}); }); it("tokenizes 'super'", function() { const {tokens} = grammar.tokenizeLine('super'); - return expect(tokens[0]).toEqual({value: 'super', scopes: ['source.coffee', 'variable.language.super.coffee']}); + expect(tokens[0]).toEqual({value: 'super', scopes: ['source.coffee', 'variable.language.super.coffee']}); }); it("tokenizes 'arguments'", function() { @@ -581,10 +575,10 @@ Until here expect(tokens[0]).toEqual({value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee']}); ({tokens} = grammar.tokenizeLine('arguments.length')); - return expect(tokens[0]).toEqual({value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee']}); + expect(tokens[0]).toEqual({value: 'arguments', scopes: ['source.coffee', 'variable.language.arguments.coffee']}); }); - return it("tokenizes illegal identifiers", function() { + it("tokenizes illegal identifiers", function() { let {tokens} = grammar.tokenizeLine('0illegal'); expect(tokens[0]).toEqual({value: '0illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); @@ -592,7 +586,7 @@ Until here expect(tokens[0]).toEqual({value: '123illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); ({tokens} = grammar.tokenizeLine('123$illegal')); - return expect(tokens[0]).toEqual({value: '123$illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + expect(tokens[0]).toEqual({value: '123$illegal', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); }); }); @@ -609,10 +603,10 @@ Until here ({tokens} = grammar.tokenizeLine('obj?.prop')); expect(tokens[0]).toEqual({value: 'obj', scopes: ['source.coffee', 'variable.other.object.coffee']}); - return expect(tokens[1]).toEqual({value: '?', scopes: ['source.coffee', 'keyword.operator.existential.coffee']}); + expect(tokens[1]).toEqual({value: '?', scopes: ['source.coffee', 'keyword.operator.existential.coffee']}); }); - return it("tokenizes illegal objects", function() { + it("tokenizes illegal objects", function() { let {tokens} = grammar.tokenizeLine('1.prop'); expect(tokens[0]).toEqual({value: '1', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); @@ -620,7 +614,7 @@ Until here expect(tokens[0]).toEqual({value: '123', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); ({tokens} = grammar.tokenizeLine('123a.prop')); - return expect(tokens[0]).toEqual({value: '123a', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); + expect(tokens[0]).toEqual({value: '123a', scopes: ['source.coffee', 'invalid.illegal.identifier.coffee']}); }); }); @@ -632,10 +626,10 @@ Until here expect(tokens[2]).toEqual({value: ',', scopes: ['source.coffee', 'punctuation.separator.delimiter.coffee']}); expect(tokens[3]).toEqual({value: ' ', scopes: ['source.coffee']}); expect(tokens[9]).toEqual({value: '3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); - return expect(tokens[10]).toEqual({value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee']}); + expect(tokens[10]).toEqual({value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee']}); }); - return it("tokenizes inclusive and exclusive slices", function() { + it("tokenizes inclusive and exclusive slices", function() { let {tokens} = grammar.tokenizeLine('[a..3]'); expect(tokens[0]).toEqual({value: '[', scopes: ['source.coffee', 'punctuation.definition.array.begin.bracket.square.coffee']}); expect(tokens[1]).toEqual({value: 'a', scopes: ['source.coffee']}); @@ -648,7 +642,7 @@ Until here expect(tokens[1]).toEqual({value: '3', scopes: ['source.coffee', 'constant.numeric.decimal.coffee']}); expect(tokens[2]).toEqual({value: '...', scopes: ['source.coffee', 'keyword.operator.slice.exclusive.coffee']}); expect(tokens[3]).toEqual({value: 'b', scopes: ['source.coffee']}); - return expect(tokens[4]).toEqual({value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee']}); + expect(tokens[4]).toEqual({value: ']', scopes: ['source.coffee', 'punctuation.definition.array.end.bracket.square.coffee']}); }); }); @@ -657,13 +651,13 @@ Until here expect(source.search(/{,/)).toEqual(-1); source = fs.readFileSync(path.resolve(__dirname, '..', 'grammars', 'coffeescript (literate).cson'), 'utf8'); - return expect(source.search(/{,/)).toEqual(-1); + expect(source.search(/{,/)).toEqual(-1); }); it("tokenizes embedded JavaScript", function() { waitsForPromise(() => atom.packages.activatePackage("language-javascript")); - return runs(function() { + runs(function() { let {tokens} = grammar.tokenizeLine("`;`"); expect(tokens[0]).toEqual({value: "`", scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.begin.coffee"]}); expect(tokens[1]).toEqual({value: ";", scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "punctuation.terminator.statement.js"]}); @@ -685,7 +679,7 @@ a = 2\ expect(tokens[1]).toEqual({value: '//', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "comment.line.double-slash.js", "punctuation.definition.comment.js"]}); expect(tokens[2]).toEqual({value: ' comment', scopes: ["source.coffee", "string.quoted.script.coffee", "source.js.embedded.coffee", "comment.line.double-slash.js"]}); expect(tokens[3]).toEqual({value: '`', scopes: ["source.coffee", "string.quoted.script.coffee", "punctuation.definition.string.end.coffee"]}); - return expect(tokens[5]).toEqual({value: 'a', scopes: ["source.coffee", "variable.assignment.coffee"]});}); + expect(tokens[5]).toEqual({value: 'a', scopes: ["source.coffee", "variable.assignment.coffee"]});}); }); describe("function calls", function() { @@ -801,7 +795,7 @@ a = 2\ ({tokens} = grammar.tokenizeLine("$ @$")); expect(tokens[0]).toEqual({value: "$", scopes: ["source.coffee", "meta.function-call.coffee", "entity.name.function.coffee"]}); - return expect(tokens[2]).toEqual({value: "@$", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "variable.other.readwrite.instance.coffee"]}); + expect(tokens[2]).toEqual({value: "@$", scopes: ["source.coffee", "meta.function-call.coffee", "meta.arguments.coffee", "variable.other.readwrite.instance.coffee"]}); }); it("tokenizes function calls when they are arguments", function() { @@ -817,14 +811,14 @@ a = 2\ ({tokens} = grammar.tokenizeLine('a b c')); expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); - return expect(tokens[4]).toEqual({value: 'c', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee']}); + expect(tokens[4]).toEqual({value: 'c', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee']}); }); it("tokenizes illegal function calls", function() { const {tokens} = grammar.tokenizeLine('0illegal()'); expect(tokens[0]).toEqual({value: '0illegal', scopes: ['source.coffee', 'meta.function-call.coffee', 'invalid.illegal.identifier.coffee']}); expect(tokens[1]).toEqual({value: '(', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee']}); - return expect(tokens[2]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + expect(tokens[2]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); }); it("tokenizes illegal arguments", function() { @@ -844,7 +838,7 @@ a = 2\ ({tokens} = grammar.tokenizeLine('a 1a')); expect(tokens[0]).toEqual({value: 'a', scopes: ['source.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee']}); - return expect(tokens[2]).toEqual({value: '1a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee']}); + expect(tokens[2]).toEqual({value: '1a', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'invalid.illegal.identifier.coffee']}); }); it("tokenizes function declaration as an argument", function() { @@ -856,7 +850,7 @@ a = 2\ expect(tokens[4]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.end.bracket.round.coffee']}); expect(tokens[8]).toEqual({value: 'return', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'keyword.control.coffee']}); expect(tokens[9]).toEqual({value: ' p ', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee']}); - return expect(tokens[10]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); + expect(tokens[10]).toEqual({value: ')', scopes: ['source.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee']}); }); it("does not tokenize booleans as function calls", function() { @@ -868,14 +862,14 @@ a = 2\ ({tokens} = grammar.tokenizeLine("true if false")); expect(tokens[0]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); expect(tokens[2]).toEqual({value: "if", scopes: ["source.coffee", "keyword.control.coffee"]}); - return expect(tokens[4]).toEqual({value: "false", scopes: ["source.coffee", "constant.language.boolean.false.coffee"]}); + expect(tokens[4]).toEqual({value: "false", scopes: ["source.coffee", "constant.language.boolean.false.coffee"]}); }); - return it("does not tokenize comparison operators as function calls", function() { + it("does not tokenize comparison operators as function calls", function() { const {tokens} = grammar.tokenizeLine("if a is b"); expect(tokens[1]).toEqual({value: " a ", scopes: ["source.coffee"]}); expect(tokens[2]).toEqual({value: "is", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); - return expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); + expect(tokens[3]).toEqual({value: " b", scopes: ["source.coffee"]}); }); }); @@ -970,10 +964,10 @@ a = 2\ expect(tokens[35]).toEqual({value: "=", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "keyword.operator.assignment.coffee"]}); expect(tokens[37]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); expect(tokens[40]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); - return expect(tokens[42]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"]}); + expect(tokens[42]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.coffee", "storage.type.function.coffee"]}); }); - return it("tokenizes inline functions", function() { + it("tokenizes inline functions", function() { let {tokens} = grammar.tokenizeLine("-> true"); expect(tokens[0]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); expect(tokens[1]).toEqual({value: " ", scopes: ["source.coffee"]}); @@ -1015,7 +1009,7 @@ a = 2\ expect(tokens[6]).toEqual({value: " ", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee"]}); expect(tokens[7]).toEqual({value: ")", scopes: ["source.coffee", "meta.function.inline.coffee", "meta.parameters.coffee", "punctuation.definition.parameters.end.bracket.round.coffee"]}); expect(tokens[8]).toEqual({value: "->", scopes: ["source.coffee", "meta.function.inline.coffee", "storage.type.function.coffee"]}); - return expect(tokens[9]).toEqual({value: " ", scopes: ["source.coffee"]}); + expect(tokens[9]).toEqual({value: " ", scopes: ["source.coffee"]}); }); }); @@ -1098,7 +1092,7 @@ a = 2\ expect(tokens[1]).toEqual({value: '.', scopes: ['source.coffee', 'meta.method-call.coffee', 'punctuation.separator.method.period.coffee']}); expect(tokens[2]).toEqual({value: 'b', scopes: ['source.coffee', 'meta.method-call.coffee', 'entity.name.function.coffee']}); expect(tokens[3]).toEqual({value: ' ', scopes: ['source.coffee', 'meta.method-call.coffee']}); - return expect(tokens[4]).toEqual({value: '@$', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'variable.other.readwrite.instance.coffee']}); + expect(tokens[4]).toEqual({value: '@$', scopes: ['source.coffee', 'meta.method-call.coffee', 'meta.arguments.coffee', 'variable.other.readwrite.instance.coffee']}); })); describe("destructuring assignments", function() { @@ -1124,7 +1118,7 @@ a = 2\ ({tokens} = grammar.tokenizeLine("{'} ='}")); // Make sure this *isn't* tokenized as a destructuring assignment expect(tokens[0]).not.toEqual({value: "{", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.begin.bracket.curly.coffee"]}); - return expect(tokens[0]).toEqual({value: "{", scopes: ["source.coffee", "meta.brace.curly.coffee"]}); + expect(tokens[0]).toEqual({value: "{", scopes: ["source.coffee", "meta.brace.curly.coffee"]}); }); it("tokenizes nested destructuring assignments", function() { @@ -1136,7 +1130,7 @@ a = 2\ expect(tokens[17]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); expect(tokens[18]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); expect(tokens[19]).toEqual({value: " ", scopes: ["source.coffee"]}); - return expect(tokens[20]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[20]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); }); it("tokenizes multiple nested destructuring assignments", function() { @@ -1148,13 +1142,13 @@ a = 2\ expect(tokens[20]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); expect(tokens[21]).toEqual({value: "}", scopes: ["source.coffee", "meta.variable.assignment.destructured.object.coffee", "punctuation.definition.destructuring.end.bracket.curly.coffee"]}); expect(tokens[22]).toEqual({value: " ", scopes: ["source.coffee"]}); - return expect(tokens[23]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); + expect(tokens[23]).toEqual({value: "=", scopes: ["source.coffee", "keyword.operator.assignment.coffee"]}); }); - return it("doesn't tokenize nested brackets as destructuring assignments", function() { + it("doesn't tokenize nested brackets as destructuring assignments", function() { const {tokens} = grammar.tokenizeLine("[Point(0, 1), [Point(0, 0), Point(0, 1)]]"); expect(tokens[0]).not.toEqual({value: "[", scopes: ["source.coffee", "meta.variable.assignment.destructured.array.coffee", "punctuation.definition.destructuring.begin.bracket.square.coffee"]}); - return expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); + expect(tokens[0]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); }); }); @@ -1163,7 +1157,7 @@ a = 2\ expect(tokens[0]).toEqual({value: "return", scopes: ["source.coffee", "keyword.control.coffee"]}); expect(tokens[2]).toEqual({value: "0", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); expect(tokens[4]).toEqual({value: "unless", scopes: ["source.coffee", "keyword.control.coffee"]}); - return expect(tokens[6]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); + expect(tokens[6]).toEqual({value: "true", scopes: ["source.coffee", "constant.language.boolean.true.coffee"]}); }); describe("for loops", function() { @@ -1172,7 +1166,7 @@ a = 2\ expect(tokens[0]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); expect(tokens[1]).toEqual({value: " food ", scopes: ["source.coffee"]}); expect(tokens[2]).toEqual({value: "in", scopes: ["source.coffee", "keyword.control.coffee"]}); - return expect(tokens[3]).toEqual({value: " foods", scopes: ["source.coffee"]}); + expect(tokens[3]).toEqual({value: " foods", scopes: ["source.coffee"]}); }); it("tokenizes for-of loops", function() { @@ -1182,7 +1176,7 @@ a = 2\ expect(tokens[2]).toEqual({value: ",", scopes: ["source.coffee", "punctuation.separator.delimiter.coffee"]}); expect(tokens[3]).toEqual({value: " type ", scopes: ["source.coffee"]}); expect(tokens[4]).toEqual({value: "of", scopes: ["source.coffee", "keyword.control.coffee"]}); - return expect(tokens[5]).toEqual({value: " foods", scopes: ["source.coffee"]}); + expect(tokens[5]).toEqual({value: " foods", scopes: ["source.coffee"]}); }); it("tokenizes loops using arrays", function() { @@ -1192,7 +1186,7 @@ a = 2\ expect(tokens[2]).toEqual({value: "in", scopes: ["source.coffee", "keyword.control.coffee"]}); expect(tokens[3]).toEqual({value: " ", scopes: ["source.coffee"]}); expect(tokens[4]).toEqual({value: "[", scopes: ["source.coffee", "punctuation.definition.array.begin.bracket.square.coffee"]}); - return expect(tokens[18]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); + expect(tokens[18]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); }); it("tokenizes loops using the optional `when` keyword", function() { @@ -1202,17 +1196,17 @@ a = 2\ expect(tokens[4]).toEqual({value: "when", scopes: ["source.coffee", "keyword.control.coffee"]}); expect(tokens[5]).toEqual({value: " food ", scopes: ["source.coffee"]}); expect(tokens[6]).toEqual({value: "isnt", scopes: ["source.coffee", "keyword.operator.comparison.coffee"]}); - return expect(tokens[7]).toEqual({value: " chocolate", scopes: ["source.coffee"]}); + expect(tokens[7]).toEqual({value: " chocolate", scopes: ["source.coffee"]}); }); - return it("tokenizes loops using the optional `by` keyword", function() { + it("tokenizes loops using the optional `by` keyword", function() { const {tokens} = grammar.tokenizeLine("for food in foods by -1"); expect(tokens[0]).toEqual({value: "for", scopes: ["source.coffee", "keyword.control.coffee"]}); expect(tokens[3]).toEqual({value: " foods ", scopes: ["source.coffee"]}); expect(tokens[4]).toEqual({value: "by", scopes: ["source.coffee", "keyword.control.coffee"]}); expect(tokens[5]).toEqual({value: " ", scopes: ["source.coffee"]}); expect(tokens[6]).toEqual({value: "-", scopes: ["source.coffee", "keyword.operator.coffee"]}); - return expect(tokens[7]).toEqual({value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); + expect(tokens[7]).toEqual({value: "1", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); }); }); @@ -1235,14 +1229,14 @@ a = 2\ expect(tokens[2]).toEqual({value: " ", scopes: ["source.coffee"]}); expect(tokens[3]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); expect(tokens[4]).toEqual({value: "test", scopes: ["source.coffee", "string.regexp.coffee"]}); - return expect(tokens[5]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + expect(tokens[5]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); }); it("tokenizes regular expressions containing spaces", function() { const {tokens} = grammar.tokenizeLine("/ te st /"); expect(tokens[0]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); expect(tokens[1]).toEqual({value: " te st ", scopes: ["source.coffee", "string.regexp.coffee"]}); - return expect(tokens[2]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + expect(tokens[2]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); }); it("tokenizes regular expressions containing escaped forward slashes", function() { @@ -1259,7 +1253,7 @@ a = 2\ expect(tokens[3]).toEqual({value: "two!", scopes: ["source.coffee", "string.regexp.coffee"]}); expect(tokens[4]).toEqual({value: "\\/", scopes: ["source.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"]}); expect(tokens[5]).toEqual({value: "three", scopes: ["source.coffee", "string.regexp.coffee"]}); - return expect(tokens[6]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); + expect(tokens[6]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); }); it("tokenizes regular expressions inside arrays", function() { @@ -1278,7 +1272,7 @@ a = 2\ expect(tokens[4]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); expect(tokens[5]).toEqual({value: "test", scopes: ["source.coffee", "string.regexp.coffee"]}); expect(tokens[6]).toEqual({value: "/", scopes: ["source.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); - return expect(tokens[7]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); + expect(tokens[7]).toEqual({value: "]", scopes: ["source.coffee", "punctuation.definition.array.end.bracket.square.coffee"]}); }); it("does not tokenize multiple division as regex", function() { @@ -1291,7 +1285,7 @@ a = 2\ ({tokens} = grammar.tokenizeLine("a / 2 / (3)")); expect(tokens[1]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); expect(tokens[3]).toEqual({value: "2", scopes: ["source.coffee", "constant.numeric.decimal.coffee"]}); - return expect(tokens[5]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); + expect(tokens[5]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); }); it("does not tokenize comments with URLs in them as regex", function() { @@ -1299,7 +1293,7 @@ a = 2\ const {tokens} = grammar.tokenizeLine("canvas.width/2 # https://github.com/atom/language-coffee-script/issues/112"); expect(tokens[3]).toEqual({value: "/", scopes: ["source.coffee", "keyword.operator.coffee"]}); expect(tokens[6]).toEqual({value: "#", scopes: ["source.coffee", "comment.line.number-sign.coffee", "punctuation.definition.comment.coffee"]}); - return expect(tokens[7]).toEqual({value: " https://github.com/atom/language-coffee-script/issues/112", scopes: ["source.coffee", "comment.line.number-sign.coffee"]}); + expect(tokens[7]).toEqual({value: " https://github.com/atom/language-coffee-script/issues/112", scopes: ["source.coffee", "comment.line.number-sign.coffee"]}); }); it("stops tokenizing regex at the first non-escaped forwards slash", function() { @@ -1312,10 +1306,10 @@ a = 2\ expect(tokens[4]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.begin.coffee"]}); expect(tokens[6]).toEqual({value: "\\/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "constant.character.escape.backslash.regexp"]}); expect(tokens[7]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.regexp.coffee", "punctuation.definition.string.end.coffee"]}); - return expect(tokens[12]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.quoted.single.coffee"]}); + expect(tokens[12]).toEqual({value: "/", scopes: ["source.coffee", "meta.method-call.coffee", "meta.arguments.coffee", "string.quoted.single.coffee"]}); }); - return it("tokenises multi-line regular expressions", function() { + it("tokenises multi-line regular expressions", function() { const {tokens} = grammar.tokenizeLine('/// (XYZ) ///'); expect(tokens[0]).toEqual({value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.begin.coffee']}); expect(tokens[2]).toEqual({value: '(', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'meta.group.regexp', 'punctuation.definition.group.regexp']}); @@ -1333,7 +1327,7 @@ XYZ // expect(lines[0][0]).toEqual({value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.begin.coffee']}); expect(lines[1][0]).toEqual({value: 'XYZ //', scopes: ['source.coffee', 'string.regexp.multiline.coffee']}); expect(lines[2][0]).toEqual({value: '/~/', scopes: ['source.coffee', 'string.regexp.multiline.coffee']}); - return expect(lines[3][0]).toEqual({value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.end.coffee']}); + expect(lines[3][0]).toEqual({value: '///', scopes: ['source.coffee', 'string.regexp.multiline.coffee', 'punctuation.definition.string.end.coffee']}); }); }); @@ -1354,10 +1348,10 @@ XYZ '' expect(lines[0][0]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.begin.coffee']}); expect(lines[1][0]).toEqual({value: "'ABC'", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee']}); expect(lines[2][0]).toEqual({value: "XYZ ''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee']}); - return expect(lines[3][0]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.end.coffee']}); + expect(lines[3][0]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.end.coffee']}); }); - return it("tokenises double-quoted here-docs", function() { + it("tokenises double-quoted here-docs", function() { const {tokens} = grammar.tokenizeLine("'''XYZ'''"); expect(tokens[0]).toEqual({value: "'''", scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee', 'punctuation.definition.string.begin.coffee']}); expect(tokens[1]).toEqual({value: 'XYZ', scopes: ['source.coffee', 'string.quoted.single.heredoc.coffee']}); @@ -1373,7 +1367,7 @@ XYZ "" expect(lines[0][0]).toEqual({value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.begin.coffee']}); expect(lines[1][0]).toEqual({value: '"ABC"', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee']}); expect(lines[2][0]).toEqual({value: 'XYZ ""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee']}); - return expect(lines[3][0]).toEqual({value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.end.coffee']}); + expect(lines[3][0]).toEqual({value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.end.coffee']}); }); }); @@ -1402,10 +1396,10 @@ XYZ "" expect(tokens[6]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); expect(tokens[7]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); expect(tokens[8]).toEqual({value: 'b', scopes: ['source.coffee', 'string.quoted.double.coffee', 'constant.character.escape.backslash.coffee']}); - return expect(tokens[9]).toEqual({value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee']}); + expect(tokens[9]).toEqual({value: '"', scopes: ['source.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee']}); }); - return it("tokenises leading backslashes in single-quoted strings", function() { + it("tokenises leading backslashes in single-quoted strings", function() { let {tokens} = grammar.tokenizeLine("'a\\\\b\\\\\\\\c'"); expect(tokens[0]).toEqual({value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.begin.coffee']}); expect(tokens[1]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.single.coffee']}); @@ -1429,7 +1423,7 @@ XYZ "" expect(tokens[6]).toEqual({value: 'a', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); expect(tokens[7]).toEqual({value: '\\', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee', 'punctuation.definition.escape.backslash.coffee']}); expect(tokens[8]).toEqual({value: 'b', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']}); - return expect(tokens[9]).toEqual({value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee']}); + expect(tokens[9]).toEqual({value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee']}); }); }); @@ -1446,7 +1440,7 @@ XYZ "" ({tokens} = grammar.tokenizeLine("
")); expect(tokens[0]).toEqual({value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']}); expect(tokens[1]).toEqual({value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]}); - return expect(tokens[2]).toEqual({value: '/>', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + expect(tokens[2]).toEqual({value: '/>', scopes: ['source.coffee', 'meta.tag.coffee' ]}); }); it("tokenises HTML tags with attributes", function() { @@ -1465,10 +1459,10 @@ XYZ "" expect(tokens[11]).toEqual({value: '"', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee' ]}); expect(tokens[12]).toEqual({value: 'myid', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee' ]}); expect(tokens[13]).toEqual({value: '"', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee' ]}); - return expect(tokens[14]).toEqual({value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ]}); + expect(tokens[14]).toEqual({value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ]}); }); - return it("tokenises HTML tags with attributes that have expressions", function() { + it("tokenises HTML tags with attributes that have expressions", function() { const {tokens} = grammar.tokenizeLine("
@handleClick(e)}>"); expect(tokens[0]).toEqual({value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']}); expect(tokens[1]).toEqual({value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]}); @@ -1486,11 +1480,11 @@ XYZ "" expect(tokens[13]).toEqual({value: 'e', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee' ]}); expect(tokens[14]).toEqual({value: ')', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee' ]}); expect(tokens[15]).toEqual({value: '}', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.brace.curly.coffee']}); - return expect(tokens[16]).toEqual({value: '>', scopes: ['source.coffee', 'meta.tag.coffee']}); + expect(tokens[16]).toEqual({value: '>', scopes: ['source.coffee', 'meta.tag.coffee']}); }); }); - return describe("firstLineMatch", function() { + describe("firstLineMatch", function() { it("recognises interpreter directives", function() { let line; const valid = `\ @@ -1574,7 +1568,7 @@ XYZ "" })(); }); - return it("recognises Vim modelines", function() { + it("recognises Vim modelines", function() { let line; const valid = `\ vim: se filetype=coffee: From 016aa0844974bd63f40ebffe7e44ef637d5948dc Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 18:06:23 -0700 Subject: [PATCH 06/18] Decaf `language-csharp` --- .../language-csharp/spec/grammar-spec.coffee | 17 ----------------- packages/language-csharp/spec/grammar-spec.js | 12 ++++-------- 2 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 packages/language-csharp/spec/grammar-spec.coffee diff --git a/packages/language-csharp/spec/grammar-spec.coffee b/packages/language-csharp/spec/grammar-spec.coffee deleted file mode 100644 index 34fcbfac99..0000000000 --- a/packages/language-csharp/spec/grammar-spec.coffee +++ /dev/null @@ -1,17 +0,0 @@ -describe "Language C# package", -> - - beforeEach -> - waitsForPromise -> - atom.packages.activatePackage("language-csharp") - - describe "C# Script grammar", -> - it "parses the grammar", -> - grammar = atom.grammars.grammarForScopeName("source.csx") - expect(grammar).toBeDefined() - expect(grammar.scopeName).toBe "source.csx" - - describe "C# Cake grammar", -> - it "parses the grammar", -> - grammar = atom.grammars.grammarForScopeName("source.cake") - expect(grammar).toBeDefined() - expect(grammar.scopeName).toBe "source.cake" diff --git a/packages/language-csharp/spec/grammar-spec.js b/packages/language-csharp/spec/grammar-spec.js index b81fbfa077..14b376cf7a 100644 --- a/packages/language-csharp/spec/grammar-spec.js +++ b/packages/language-csharp/spec/grammar-spec.js @@ -1,8 +1,4 @@ -/* - * decaffeinate suggestions: - * DS102: Remove unnecessary code created because of implicit returns - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe("Language C# package", function() { beforeEach(() => waitsForPromise(() => atom.packages.activatePackage("language-csharp"))); @@ -10,12 +6,12 @@ describe("Language C# package", function() { describe("C# Script grammar", () => it("parses the grammar", function() { const grammar = atom.grammars.grammarForScopeName("source.csx"); expect(grammar).toBeDefined(); - return expect(grammar.scopeName).toBe("source.csx"); + expect(grammar.scopeName).toBe("source.csx"); })); - return describe("C# Cake grammar", () => it("parses the grammar", function() { + describe("C# Cake grammar", () => it("parses the grammar", function() { const grammar = atom.grammars.grammarForScopeName("source.cake"); expect(grammar).toBeDefined(); - return expect(grammar.scopeName).toBe("source.cake"); + expect(grammar.scopeName).toBe("source.cake"); })); }); From d51de562164dba006dad55f7573890abc4562cc7 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 18:10:41 -0700 Subject: [PATCH 07/18] Decaf `language-css` --- packages/language-css/spec/css-spec.coffee | 3638 -------------------- packages/language-css/spec/css-spec.js | 494 ++- 2 files changed, 244 insertions(+), 3888 deletions(-) delete mode 100644 packages/language-css/spec/css-spec.coffee diff --git a/packages/language-css/spec/css-spec.coffee b/packages/language-css/spec/css-spec.coffee deleted file mode 100644 index 66d14a3e09..0000000000 --- a/packages/language-css/spec/css-spec.coffee +++ /dev/null @@ -1,3638 +0,0 @@ -describe 'CSS grammar', -> - grammar = null - - beforeEach -> - atom.config.set 'core.useTreeSitterParsers', false - - waitsForPromise -> - atom.packages.activatePackage('language-css') - - runs -> - grammar = atom.grammars.grammarForScopeName('source.css') - - it 'parses the grammar', -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe 'source.css' - - describe 'selectors', -> - it 'tokenizes type selectors', -> - {tokens} = grammar.tokenizeLine 'p {}' - expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - - it 'tokenizes the universal selector', -> - {tokens} = grammar.tokenizeLine '*' - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - - it 'tokenises combinators', -> - {tokens} = grammar.tokenizeLine 'a > b + * ~ :not(.nah)' - expect(tokens[2]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(tokens[6]).toEqual value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(tokens[10]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - - it 'highlights deprecated combinators', -> - {tokens} = grammar.tokenizeLine '.sooo /deep/ >>>_.>>>' - expect(tokens[3]).toEqual value: '/deep/', scopes: ['source.css', 'invalid.deprecated.combinator.css'] - expect(tokens[5]).toEqual value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css'] - - it 'tokenizes complex selectors', -> - {tokens} = grammar.tokenizeLine '[disabled], [disabled] + p' - expect(tokens[0]).toEqual value: '[', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.begin.bracket.square.css"] - expect(tokens[1]).toEqual value: 'disabled', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "entity.other.attribute-name.css"] - expect(tokens[2]).toEqual value: ']', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.end.bracket.square.css"] - expect(tokens[3]).toEqual value: ',', scopes: ["source.css", "meta.selector.css", "punctuation.separator.list.comma.css"] - expect(tokens[5]).toEqual value: '[', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.begin.bracket.square.css"] - expect(tokens[6]).toEqual value: 'disabled', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "entity.other.attribute-name.css"] - expect(tokens[7]).toEqual value: ']', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.end.bracket.square.css"] - expect(tokens[9]).toEqual value: '+', scopes: ["source.css", "meta.selector.css", "keyword.operator.combinator.css"] - expect(tokens[11]).toEqual value: 'p', scopes: ["source.css", "meta.selector.css", "entity.name.tag.css"] - - lines = grammar.tokenizeLines """ - [disabled]:not(:first-child)::before:hover - ~ div.object - + #id.thing:hover > strong ~ p::before, - a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], - *>em.i.ly[data-name|="Life"] { } - """ - expect(lines[0][0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[0][1]).toEqual value: 'disabled', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[0][2]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(lines[0][3]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][4]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[0][5]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[0][6]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][7]).toEqual value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[0][8]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[0][9]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(lines[0][10]).toEqual value: 'before', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[0][11]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][12]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[1][1]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[1][3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[1][4]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[1][5]).toEqual value: 'object', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[2][1]).toEqual value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[2][3]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(lines[2][4]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(lines[2][5]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[2][6]).toEqual value: 'thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[2][7]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[2][8]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[2][10]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[2][12]).toEqual value: 'strong', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[2][14]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[2][16]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[2][17]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(lines[2][18]).toEqual value: 'before', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[2][19]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[3][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'invalid.illegal.colon.css'] - expect(lines[3][3]).toEqual value: 'last-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[3][4]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][5]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][6]).toEqual value: 'Comment', scopes: ['source.css', 'comment.block.css'] - expect(lines[3][7]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[3][8]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(lines[3][9]).toEqual value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[3][11]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[3][13]).toEqual value: 'html', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[3][14]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[3][15]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[3][16]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[3][17]).toEqual value: 'en-AU', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(lines[3][18]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(lines[3][19]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(lines[4][1]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[4][2]).toEqual value: 'em', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][3]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[4][4]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[4][5]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[4][6]).toEqual value: 'ly', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[4][7]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[4][8]).toEqual value: 'data-name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[4][9]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[4][10]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[4][11]).toEqual value: 'Life', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(lines[4][12]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[4][13]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(lines[4][15]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[4][17]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'custom elements (as type selectors)', -> - it 'only tokenizes identifiers beginning with [a-z]', -> - {tokens} = grammar.tokenizeLine 'pearl-1941 1941-pearl -pearl-1941' - expect(tokens[0]).toEqual value: 'pearl-1941', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css'] - - it 'tokenizes custom elements containing non-ASCII letters', -> - {tokens} = grammar.tokenizeLine 'pokémon-ピカチュウ' - expect(tokens[0]).toEqual value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - - it 'does not tokenize identifiers containing [A-Z]', -> - {tokens} = grammar.tokenizeLine 'Basecamp-schedule basecamp-Schedule' - expect(tokens[0]).toEqual value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css'] - - it 'does not tokenize identifiers containing no hyphens', -> - {tokens} = grammar.tokenizeLine 'halo_night' - expect(tokens[0]).toEqual value: 'halo_night', scopes: ['source.css', 'meta.selector.css'] - - it 'does not tokenise identifiers following an @ symbol', -> - {tokens} = grammar.tokenizeLine('@some-weird-new-feature') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - it 'does not tokenise identifiers in unfamiliar functions', -> - {tokens} = grammar.tokenizeLine('some-edgy-new-function()') - expect(tokens[0]).toEqual value: 'some-edgy-new-function(', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[1]).toEqual value: ')', scopes: ['source.css'] - - describe 'attribute selectors', -> - it 'tokenizes attribute selectors without values', -> - {tokens} = grammar.tokenizeLine '[title]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[2]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes attribute selectors with identifier values', -> - {tokens} = grammar.tokenizeLine '[hreflang|=fr]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: 'hreflang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[2]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[3]).toEqual value: 'fr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[4]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes attribute selectors with string values', -> - {tokens} = grammar.tokenizeLine '[href^="http://www.w3.org/"]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: 'href', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[2]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'http://www.w3.org/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes CSS qualified attribute names with wildcard prefix', -> - {tokens} = grammar.tokenizeLine '[*|title]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[3]).toEqual value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[4]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes CSS qualified attribute names with namespace prefix', -> - {tokens} = grammar.tokenizeLine '[marvel|origin=radiation]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: 'marvel', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[3]).toEqual value: 'origin', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[4]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[5]).toEqual value: 'radiation', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes CSS qualified attribute names without namespace prefix', -> - {tokens} = grammar.tokenizeLine '[|data-hp="75"]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: 'data-hp', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[5]).toEqual value: '75', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises compound ID/attribute selectors', -> - {tokens} = grammar.tokenizeLine('#div[id="0"]{ }') - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[2]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[3]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[8]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - {tokens} = grammar.tokenizeLine('.bar#div[id="0"]') - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'bar', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[2]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[4]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[5]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - - it 'tokenises compound class/attribute selectors', -> - {tokens} = grammar.tokenizeLine('.div[id="0"]{ }') - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[2]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[3]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[8]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - {tokens} = grammar.tokenizeLine('#bar.div[id]') - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'bar', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[2]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[4]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[5]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'allows whitespace to be inserted between tokens', -> - {tokens} = grammar.tokenizeLine('span[ er|lang |= "%%" ]') - expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[3]).toEqual value: 'er', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[4]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[5]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[7]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[10]).toEqual value: '%%', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[11]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[12]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[13]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises escape sequences inside attribute selectors', -> - {tokens} = grammar.tokenizeLine('a[name\\[0\\]="value"]') - expect(tokens[2]).toEqual value: 'name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[3]).toEqual value: '\\[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] - expect(tokens[4]).toEqual value: '0', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[5]).toEqual value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] - expect(tokens[6]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[10]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises escape sequences inside namespace prefixes', -> - {tokens} = grammar.tokenizeLine('a[name\\ space|Get\\ It\\?="kek"]') - expect(tokens[2]).toEqual value: 'name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[3]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css', 'constant.character.escape.css'] - expect(tokens[4]).toEqual value: 'space', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[5]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[6]).toEqual value: 'Get', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[7]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] - expect(tokens[8]).toEqual value: 'It', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[9]).toEqual value: '\\?', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] - expect(tokens[10]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[14]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises comments inside attribute selectors', -> - {tokens} = grammar.tokenizeLine('span[/*]*/lang]') - expect(tokens[0]).toEqual value: 'span', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises quoted strings in attribute selectors', -> - {tokens} = grammar.tokenizeLine('a[href^="#"] a[href^= "#"] a[href^="#" ]') - expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[5]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[12]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[13]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[14]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[15]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[16]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[23]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[24]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[25]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[26]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[27]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - {tokens} = grammar.tokenizeLine("a[href^='#'] a[href^= '#'] a[href^='#' ]") - expect(tokens[4]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[5]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] - expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[12]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[13]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[14]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[15]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] - expect(tokens[16]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[23]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[24]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] - expect(tokens[25]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[26]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[27]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises unquoted strings in attribute selectors', -> - {tokens} = grammar.tokenizeLine('span[class~=Java]') - expect(tokens[3]).toEqual value: '~=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[4]).toEqual value: 'Java', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[5]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - {tokens} = grammar.tokenizeLine('span[class^= 0xDEADCAFE=|~BEEFBABE ]') - expect(tokens[3]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[5]).toEqual value: '0xDEADCAFE=|~BEEFBABE', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises escape sequences in unquoted strings', -> - {tokens} = grammar.tokenizeLine('a[name\\[0\\]=a\\BAD\\AF\\]a\\ i] {}') - expect(tokens[6]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[7]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[8]).toEqual value: '\\BAD', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.codepoint.css'] - expect(tokens[9]).toEqual value: '\\AF', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.codepoint.css'] - expect(tokens[10]).toEqual value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css'] - expect(tokens[11]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[12]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css'] - expect(tokens[13]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[14]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[16]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises the ignore-case modifier at the end of a selector', -> - {tokens} = grammar.tokenizeLine('a[attr=val i] a[attr="val" i] a[attr=\'val\'I] a[val^= \'"\'i] a[attr= i] a[attr= i i]') - expect(tokens[6]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[16]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[17]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[26]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[27]).toEqual value: 'I', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[28]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[34]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[35]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[36]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] - expect(tokens[37]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[38]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[39]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[44]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[45]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[46]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[47]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[52]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[53]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[54]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[55]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[56]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[57]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises attribute selectors spanning multiple lines', -> - lines = grammar.tokenizeLines """ - span[ - \\x20{2} - ns|lang/**/ - |= - "pt"] - """ - expect(lines[0][0]).toEqual value: 'span', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[0][1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[1][0]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(lines[2][1]).toEqual value: 'ns', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(lines[2][2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(lines[2][3]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][5]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[3][1]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[4][0]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[4][1]).toEqual value: 'pt', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(lines[4][2]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[4][3]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - lines = grammar.tokenizeLines """ - span[/*=== - ==|span[/*} - ====*/*|lang/*]=*/~=/*"|"*/"en-AU"/* - | - */ - i] - """ - expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][3]).toEqual value: '===', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[1][0]).toEqual value: '==|span[/*}', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[2][0]).toEqual value: '====', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(lines[2][3]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(lines[2][4]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[2][5]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][6]).toEqual value: ']=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[2][7]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][8]).toEqual value: '~=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[2][9]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][10]).toEqual value: '"|"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[2][11]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][12]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[2][13]).toEqual value: 'en-AU', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(lines[2][14]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[2][15]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][0]).toEqual value: ' |', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[4][0]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[5][0]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(lines[5][1]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - describe 'class selectors', -> - it 'tokenizes class selectors containing non-ASCII letters', -> - {tokens} = grammar.tokenizeLine '.étendard' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'étendard', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - {tokens} = grammar.tokenizeLine '.スポンサー' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - it 'tokenizes a class selector consisting of two hypens', -> - {tokens} = grammar.tokenizeLine '.--' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - it 'tokenizes class selectors consisting of one (valid) character', -> - {tokens} = grammar.tokenizeLine '._' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - it 'tokenises class selectors starting with an escape sequence', -> - {tokens} = grammar.tokenizeLine '.\\33\\44-model {' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css'] - expect(tokens[2]).toEqual value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css'] - expect(tokens[3]).toEqual value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises class selectors ending with an escape sequence', -> - {tokens} = grammar.tokenizeLine '.la\\{tex\\} {' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css'] - expect(tokens[3]).toEqual value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[4]).toEqual value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css'] - expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks a class invalid if it contains unescaped ASCII punctuation or symbols other than "-" and "_"', -> - {tokens} = grammar.tokenizeLine '.B&W{' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'B&W', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks a class invalid if it starts with ASCII digits ([0-9])', -> - {tokens} = grammar.tokenizeLine '.666{' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks a class invalid if it starts with "-" followed by ASCII digits', -> - {tokens} = grammar.tokenizeLine '.-911-{' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks a class invalid if it consists of only one hyphen', -> - {tokens} = grammar.tokenizeLine '.-{' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - describe 'id selectors', -> - it 'tokenizes id selectors consisting of ASCII letters', -> - {tokens} = grammar.tokenizeLine '#unicorn' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - - it 'tokenizes id selectors containing non-ASCII letters', -> - {tokens} = grammar.tokenizeLine '#洪荒之力' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - - it 'tokenizes id selectors containing [0-9], "-", or "_"', -> - {tokens} = grammar.tokenizeLine '#_zer0-day' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - - it 'tokenizes id selectors beginning with two hyphens', -> - {tokens} = grammar.tokenizeLine '#--d3bug--' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - - it 'marks an id invalid if it contains ASCII punctuation or symbols other than "-" and "_"', -> - {tokens} = grammar.tokenizeLine '#sort!{' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'sort!', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks an id invalid if it starts with ASCII digits ([0-9])', -> - {tokens} = grammar.tokenizeLine '#666{' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks an id invalid if it starts with "-" followed by ASCII digits', -> - {tokens} = grammar.tokenizeLine '#-911-{' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks an id invalid if it consists of one hyphen only', -> - {tokens} = grammar.tokenizeLine '#-{' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises ID selectors starting with an escape sequence', -> - {tokens} = grammar.tokenizeLine '#\\33\\44-model {' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css'] - expect(tokens[2]).toEqual value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css'] - expect(tokens[3]).toEqual value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises ID selectors ending with an escape sequence', -> - {tokens} = grammar.tokenizeLine '#la\\{tex\\} {' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css'] - expect(tokens[3]).toEqual value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[4]).toEqual value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css'] - expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - describe 'namespace prefixes', -> - it 'tokenises arbitrary namespace prefixes', -> - {tokens} = grammar.tokenizeLine('foo|h1 { }') - expect(tokens[0]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenises anonymous namespace prefixes', -> - {tokens} = grammar.tokenizeLine('*|abbr {}') - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: 'abbr', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('*|* {}') - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('foo|* { }') - expect(tokens[0]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('|[svg|attr=name]{}') - expect(tokens[0]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[2]).toEqual value: 'svg', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[3]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[4]).toEqual value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - - it 'tokenises the "no-namespace" prefix', -> - {tokens} = grammar.tokenizeLine('|h1 { }') - expect(tokens[0]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[1]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "doesn't tokenise prefixes without a selector", -> - {tokens} = grammar.tokenizeLine('*| { }') - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('*|{ }') - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'at-rules', -> - describe '@charset', -> - # NB: \A won't match if "tokenizeLine" is used; "tokenizeLines" is used here to circumvent this limitation - it 'tokenises @charset rules at the start of a file', -> - lines = grammar.tokenizeLines '@charset "US-ASCII";' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[0][4]).toEqual value: 'US-ASCII', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] - expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[0][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines('/* Not the first line */\n@charset "UTF-8";') - expect(lines[0][0]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][1]).toEqual value: ' Not the first line ', scopes: ['source.css', 'comment.block.css'] - expect(lines[0][2]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] - expect(lines[1][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - it 'highlights invalid @charset statements', -> - lines = grammar.tokenizeLines " @charset 'US-ASCII';" - expect(lines[0][0]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.leading-whitespace.charset.css'] - expect(lines[0][1]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][2]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][4]).toEqual value: "'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-double-quoted.charset.css'] - expect(lines[0][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset "iso-8859-15";' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.whitespace.charset.css'] - expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[0][4]).toEqual value: 'iso-8859-15', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] - expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[0][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset"US-ASCII";' - expect(lines[0][0]).toEqual value: '@charset"US-ASCII"', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.no-whitespace.charset.css'] - expect(lines[0][1]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset "UTF-8" ;' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[0][4]).toEqual value: 'UTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] - expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unexpected-characters.charset.css'] - expect(lines[0][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset "WTF-8" /* Nope */ ;' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[0][4]).toEqual value: 'WTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] - expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[0][6]).toEqual value: ' /* Nope */ ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unexpected-characters.charset.css'] - expect(lines[0][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset "UTF-8' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][3]).toEqual value: '"UTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unclosed-string.charset.css'] - - lines = grammar.tokenizeLines "@CHARSET 'US-ASCII';" - expect(lines[0][0]).toEqual value: '@CHARSET', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-lowercase.charset.css'] - expect(lines[0][1]).toEqual value: " 'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - describe '@import', -> - it 'tokenises @import statements', -> - {tokens} = grammar.tokenizeLine('@import url("file.css");') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import "file.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine("@import 'file.css';") - expect(tokens[3]).toEqual value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css'] - expect(tokens[5]).toEqual value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - - it "doesn't let injected comments impact parameter matching", -> - {tokens} = grammar.tokenizeLine('@import /* url("name"); */ "1.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[4]).toEqual value: ' url("name"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[5]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import/* Comment */"2.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: ' Comment ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'correctly handles word boundaries', -> - {tokens} = grammar.tokenizeLine('@import"file.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[3]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import-file.css;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import-file', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - expect(tokens[2]).toEqual value: '.css', scopes: ['source.css', 'meta.at-rule.header.css'] - expect(tokens[3]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css'] - - it 'matches a URL that starts on the next line', -> - lines = grammar.tokenizeLines '@import\nurl("file.css");' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(lines[0][2]).toEqual value: '', scopes: ['source.css', 'meta.at-rule.import.css'] - expect(lines[1][0]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[1][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][3]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[1][5]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'matches comments inside query lists', -> - {tokens} = grammar.tokenizeLine('@import url("1.css") print /* url(";"); */ all;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[10]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[16]).toEqual value: 'all', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] - expect(tokens[17]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'highlights deprecated media types', -> - {tokens} = grammar.tokenizeLine('@import "astral.css" projection;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'astral.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[7]).toEqual value: 'projection', scopes: ['source.css', 'meta.at-rule.import.css', 'invalid.deprecated.constant.media.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'highlights media features in query lists', -> - {tokens} = grammar.tokenizeLine('@import url(\'landscape.css\') screen and (orientation:landscape);') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '\'', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'landscape.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css'] - expect(tokens[7]).toEqual value: '\'', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[14]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[15]).toEqual value: 'orientation', scopes: ['source.css', 'meta.at-rule.import.css', 'support.type.property-name.media.css'] - expect(tokens[16]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.separator.key-value.css'] - expect(tokens[17]).toEqual value: 'landscape', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.property-value.css'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[19]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - describe '@media', -> - it 'tokenises @media keywords correctly', -> - {tokens} = grammar.tokenizeLine('@media(max-width: 37.5em) { }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[3]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[7]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[9]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@media not print and (max-width: 37.5em){ }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.not.media.css'] - expect(tokens[5]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[7]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[10]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[11]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[13]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[14]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[16]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[18]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'highlights deprecated media types', -> - {tokens} = grammar.tokenizeLine('@media (max-device-width: 2px){ }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'max-device-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'highlights vendored media features', -> - {tokens} = grammar.tokenizeLine('@media (-webkit-foo: bar){ b{ } }') - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '-webkit-foo', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: ' bar', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[8]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@media screen and (-ms-high-contrast:black-on-white){ }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[5]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '-ms-high-contrast', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[9]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[10]).toEqual value: 'black-on-white', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@media (_moz-a:b){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '_moz-a', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'b', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('@media (-hp-foo:bar){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '-hp-foo', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'bar', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('@media (mso-page-size:wide){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'mso-page-size', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'wide', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - - it 'tokenises @media immediately following a closing brace', -> - {tokens} = grammar.tokenizeLine('h1 { }@media only screen { } h2 { }') - expect(tokens[0]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[5]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[6]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[8]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - expect(tokens[16]).toEqual value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[18]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[20]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('h1 { }@media only screen { }h2 { }') - expect(tokens[0]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[5]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[6]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[8]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - expect(tokens[15]).toEqual value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[17]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[19]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenises level 4 media-query syntax', -> - lines = grammar.tokenizeLines """ - @media (min-width >= 0px) - and (max-width <= 400) - and (min-height > 400) - and (max-height < 200) - """ - expect(lines[0][6]).toEqual value: '>=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] - expect(lines[1][6]).toEqual value: '<=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] - expect(lines[2][6]).toEqual value: '>', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] - expect(lines[3][6]).toEqual value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] - - it 'tokenises comments between media types', -> - {tokens} = grammar.tokenizeLine('@media/* */only/* */screen/* */and (min-width:1100px){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[9]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[10]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[12]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[13]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[15]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[16]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[17]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[18]).toEqual value: '1100', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[19]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[20]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[21]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[22]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'tokenises comments between media features', -> - {tokens} = grammar.tokenizeLine('@media/*=*/(max-width:/**/37.5em)/*=*/and/*=*/(/*=*/min-height/*:*/:/*=*/1.2em/*;*/){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[10]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[11]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[13]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[14]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[15]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[16]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[17]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[18]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[19]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[20]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[21]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[22]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[23]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[24]).toEqual value: 'min-height', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[25]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[26]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[27]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[28]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[29]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[30]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[31]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[32]).toEqual value: '1.2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[33]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[34]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[35]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[36]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[37]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[38]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[39]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'matches media queries across lines', -> - lines = grammar.tokenizeLines """ - @media only screen and (min-width : /* 40 */ - 320px), - not print and (max-width: 480px) /* kek */ and (-webkit-min-device-pixel-ratio /*:*/ : 2), - only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-ratio: 2) { } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(lines[0][3]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(lines[0][5]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(lines[0][7]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(lines[0][9]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[0][10]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(lines[0][12]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[0][14]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][15]).toEqual value: ' 40 ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(lines[0][16]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][1]).toEqual value: '320', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[1][2]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[1][3]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[1][4]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][1]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.not.media.css'] - expect(lines[2][3]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(lines[2][5]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(lines[2][7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[2][8]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(lines[2][9]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[2][11]).toEqual value: '480', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[2][12]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[2][13]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[2][15]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][16]).toEqual value: ' kek ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(lines[2][17]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][19]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(lines[2][21]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[2][22]).toEqual value: '-webkit-min-device-pixel-ratio', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(lines[2][24]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][25]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(lines[2][26]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][28]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[2][30]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[2][31]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[2][32]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][0]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(lines[3][2]).toEqual value: 'speech', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(lines[3][4]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(lines[3][6]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[3][7]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(lines[3][8]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[3][10]).toEqual value: '10', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[3][11]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[3][12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[3][13]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][15]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][16]).toEqual value: ' wat ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(lines[3][17]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[3][19]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[3][20]).toEqual value: '-webkit-min-device-pixel-ratio', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(lines[3][21]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[3][23]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[3][24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[3][26]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(lines[3][28]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'highlights invalid commas', -> - {tokens} = grammar.tokenizeLine('@media , {}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@media , ,screen {}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: ', ,', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css'] - expect(tokens[4]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'allows spaces inside ratio values', -> - {tokens} = grammar.tokenizeLine('@media (min-aspect-ratio: 3 / 4) and (max-aspect-ratio: 20 / 17) {}') - expect(tokens[7]).toEqual value: '3', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] - expect(tokens[9]).toEqual value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css'] - expect(tokens[10]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] - expect(tokens[11]).toEqual value: '4', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] - expect(tokens[20]).toEqual value: '20', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] - expect(tokens[21]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] - expect(tokens[22]).toEqual value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css'] - expect(tokens[23]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] - expect(tokens[24]).toEqual value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] - - describe '@keyframes', -> - it 'tokenises keyframe lists correctly', -> - lines = grammar.tokenizeLines """ - @keyframes important1 { - from { margin-top: 50px; - margin-bottom: 100px } - 50% { margin-top: 150px !important; } /* Ignored */ - to { margin-top: 100px; } - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(lines[0][3]).toEqual value: 'important1', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(lines[0][4]).toEqual value: ' ', scopes: ['source.css'] - expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(lines[1][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[1][8]).toEqual value: '50', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[1][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[2][1]).toEqual value: 'margin-bottom', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[2][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[3][1]).toEqual value: '50%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] - expect(lines[3][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[3][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[3][8]).toEqual value: '150', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[3][11]).toEqual value: '!important', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'keyword.other.important.css'] - expect(lines[3][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[3][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[3][16]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][17]).toEqual value: ' Ignored ', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css'] - expect(lines[3][18]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[4][1]).toEqual value: 'to', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(lines[4][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[4][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[4][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[4][8]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[4][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[5][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] - - it 'matches injected comments', -> - lines = grammar.tokenizeLines """ - @keyframes/*{*/___IDENT__/*} - { Nah { margin-top: 2em; } - */{ from - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] - expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[0][5]).toEqual value: '___IDENT__', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] - expect(lines[1][0]).toEqual value: ' { Nah { margin-top: 2em; }', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] - expect(lines[2][0]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][1]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] - expect(lines[2][3]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - - it 'matches offset keywords case-insensitively', -> - {tokens} = grammar.tokenizeLine('@keyframes Give-them-both { fROm { } To {} }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(tokens[3]).toEqual value: 'Give-them-both', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] - expect(tokens[7]).toEqual value: 'fROm', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(tokens[9]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[11]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[13]).toEqual value: 'To', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(tokens[15]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[16]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[18]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] - - it 'matches percentile offsets', -> - {tokens} = grammar.tokenizeLine('@keyframes identifier { -50.2% } @keyframes ident2 { .25%}') - expect(tokens[7]).toEqual value: '-50.2%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] - expect(tokens[18]).toEqual value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] - - it 'highlights escape sequences inside identifiers', -> - {tokens} = grammar.tokenizeLine '@keyframes A\\1F602Z' - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(tokens[3]).toEqual value: 'A', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(tokens[4]).toEqual value: '\\1F602', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[5]).toEqual value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - - describe '@supports', -> - it 'tokenises feature queries', -> - {tokens} = grammar.tokenizeLine('@supports (font-size: 1em) { }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.supports.header.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'font-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[7]).toEqual value: '1', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[10]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[11]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(tokens[13]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - it 'matches logical operators', -> - lines = grammar.tokenizeLines """ - @supports not (font-size: 1em){ } - @supports (font-size: 1em) and (font-size: 1em){ } - @supports (font-size: 1em) or (font-size: 1em){ } - """ - expect(lines[0][3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] - expect(lines[1][11]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css'] - expect(lines[2][11]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - - it 'matches custom variables in feature queries', -> - {tokens} = grammar.tokenizeLine('@supports (--foo: green){}') - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '--foo', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'variable.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[7]).toEqual value: 'green', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - - it "doesn't mistake brackets in string literals for feature queries", -> - lines = grammar.tokenizeLines """ - @supports not ((tab-size:4) or (-moz-tab-size:4)){ - body::before{content: "Come on, Microsoft (Get it together already)…"; } - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(lines[0][3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] - expect(lines[0][7]).toEqual value: 'tab-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[0][12]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'keyword.operator.logical.feature.or.css'] - expect(lines[0][15]).toEqual value: '-moz-tab-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - expect(lines[0][20]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[1][2]).toEqual value: '::', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(lines[1][3]).toEqual value: 'before', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[1][4]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][5]).toEqual value: 'content', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[1][8]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][9]).toEqual value: 'Come on, Microsoft (Get it together already)…', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[1][10]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[1][11]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[1][13]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[2][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - it 'tokenises multiple feature queries', -> - {tokens} = grammar.tokenizeLine('@supports (display:table-cell) or ((display:list-item) and (display:run-in)){') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'table-cell', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[9]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - expect(tokens[11]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[12]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[13]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[14]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[15]).toEqual value: 'list-item', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[16]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[18]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'keyword.operator.logical.feature.and.css'] - expect(tokens[20]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[21]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[22]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[23]).toEqual value: 'run-in', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[25]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[26]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - - it 'embeds rulesets and other at-rules', -> - lines = grammar.tokenizeLines """ - @supports (animation-name: test) { - #node { - animation-name: test; - } - body > header[data-name="attr"] ~ *:not(:first-child){ - content: "😂👌" - } - @keyframes important1 { - from { - margin-top: 50px; - margin-bottom: 100px - } - 50% { margin-top: 150px !important; } /* Ignored */ - to { margin-top: 100px; } - } - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(lines[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[0][4]).toEqual value: 'animation-name', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[0][7]).toEqual value: 'test', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css'] - expect(lines[0][8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[0][10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: '#', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(lines[1][2]).toEqual value: 'node', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(lines[1][4]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[2][1]).toEqual value: 'animation-name', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: 'test', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(lines[2][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[3][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[4][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][3]).toEqual value: '>', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[4][5]).toEqual value: 'header', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][6]).toEqual value: '[', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[4][7]).toEqual value: 'data-name', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[4][8]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[4][9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[4][10]).toEqual value: 'attr', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(lines[4][11]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[4][12]).toEqual value: ']', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(lines[4][14]).toEqual value: '~', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[4][16]).toEqual value: '*', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(lines[4][17]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[4][18]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[4][19]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][20]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[4][21]).toEqual value: 'first-child', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[4][22]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][23]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[5][1]).toEqual value: 'content', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[5][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[5][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[5][5]).toEqual value: '😂👌', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[5][6]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[6][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[7][1]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(lines[7][2]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(lines[7][4]).toEqual value: 'important1', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(lines[7][6]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] - expect(lines[8][1]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(lines[8][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[9][1]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[9][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[9][4]).toEqual value: '50', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[9][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[9][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[10][1]).toEqual value: 'margin-bottom', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[10][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[10][4]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[10][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[11][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[12][1]).toEqual value: '50%', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] - expect(lines[12][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[12][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[12][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[12][8]).toEqual value: '150', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[12][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[12][11]).toEqual value: '!important', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'keyword.other.important.css'] - expect(lines[12][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[12][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[12][16]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[12][17]).toEqual value: ' Ignored ', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css'] - expect(lines[12][18]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[13][1]).toEqual value: 'to', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(lines[13][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[13][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[13][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[13][8]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[13][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[13][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[13][12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[14][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] - expect(lines[15][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - it 'matches injected comments', -> - # NB: This particular example actually isn't valid @supports - # syntax; it's just for stress-testing boundary-matching. - lines = grammar.tokenizeLines """ - @supports/*===*/not/*==****************| - ==*/(display:table-cell)/*============*/ and (display: list-item)/*}*/{} - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][3]).toEqual value: '===', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[0][5]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] - expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][7]).toEqual value: '==****************|', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[1][3]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][4]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[1][5]).toEqual value: 'table-cell', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[1][7]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][8]).toEqual value: '============', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[1][9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][11]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css'] - expect(lines[1][13]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[1][19]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][20]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[1][21]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][22]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(lines[1][23]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - it 'matches feature queries across multiple lines', -> - lines = grammar.tokenizeLines """ - @supports - (box-shadow: 0 0 2px rgba(0,0,0,.5) inset) or - (-moz-box-shadow: 0 0 2px black inset) or - (-webkit-box-shadow: 0 0 2px black inset) or - (-o-box-shadow: 0 0 2px black inset) - { .noticebox { } } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(lines[1][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[1][2]).toEqual value: 'box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[1][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[1][12]).toEqual value: 'rgba', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[1][13]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][14]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][15]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][16]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][17]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][18]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][19]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][20]).toEqual value: '.5', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][21]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][23]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[1][26]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - expect(lines[2][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[2][2]).toEqual value: '-moz-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - expect(lines[2][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[2][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[2][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[2][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[2][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[2][17]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - expect(lines[3][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[3][2]).toEqual value: '-webkit-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - expect(lines[3][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[3][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[3][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[3][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[3][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[3][17]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - expect(lines[4][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[4][2]).toEqual value: '-o-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - expect(lines[4][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[4][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[4][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[4][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[4][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[5][0]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(lines[5][2]).toEqual value: '.', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[5][3]).toEqual value: 'noticebox', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[5][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[5][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[5][9]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - describe '@namespace', -> - it 'tokenises @namespace statements correctly', -> - {tokens} = grammar.tokenizeLine('@namespace "XML";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@namespace prefix "XML" ;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[3]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@namespace url("http://a.bc/");') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - it "doesn't confuse a prefix of 'url' as a function", -> - {tokens} = grammar.tokenizeLine('@namespace url url("http://a.bc/");') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[5]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[11]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - it 'permits injected comments between tokens', -> - {tokens} = grammar.tokenizeLine('@namespace/*=*/pre/*=*/"url"/*=*/;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[7]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] - expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[10]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(tokens[11]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - it 'allows no spaces between "@namespace" and quoted URLs', -> - {tokens} = grammar.tokenizeLine('@namespace"XML";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[3]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - it 'tokenises escape sequences in prefixes', -> - {tokens} = grammar.tokenizeLine('@namespace pre\\ fix "http://url/";') - expect(tokens[3]).toEqual value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[4]).toEqual value: '\\ ', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css', 'constant.character.escape.css'] - expect(tokens[5]).toEqual value: 'fix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - - it 'allows arguments to span multiple lines', -> - lines = grammar.tokenizeLines """ - @namespace - prefix"XML"; - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(lines[1][0]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(lines[1][1]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][2]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(lines[1][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[1][4]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines """ - @namespace - - prefix - - url("http://a.bc/"); - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(lines[2][1]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(lines[4][0]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[4][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[4][3]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(lines[4][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[4][5]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - describe 'font-feature declarations', -> - it 'tokenises font-feature blocks', -> - {tokens} = grammar.tokenizeLine('@font-feature-values Font name 2 { }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.font-features.css'] - expect(tokens[3]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'allows font-feature names to start on a different line', -> - lines = grammar.tokenizeLines """ - @font-feature-values - Font name 2 - { - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] - expect(lines[1][0]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(lines[2][0]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'matches injected comments', -> - {tokens} = grammar.tokenizeLine('@font-feature-values/*{*/Font/*}*/name/*{*/2{') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'Font', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] - expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[9]).toEqual value: 'name', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(tokens[10]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[11]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] - expect(tokens[12]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[13]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(tokens[14]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises at-rules for feature names', -> - lines = grammar.tokenizeLines """ - @swash{ swashy: 2; } - @ornaments{ ident: 2; } - @annotation{ ident: 1; } - @stylistic{ stylish: 2; } - @styleset{ sets: 2 3 4; } - @character-variant{ charvar: 2 } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] - expect(lines[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[0][4]).toEqual value: 'swashy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[0][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[0][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[0][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css', 'punctuation.definition.keyword.css'] - expect(lines[1][1]).toEqual value: 'ornaments', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css'] - expect(lines[1][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][4]).toEqual value: 'ident', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[1][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[1][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[1][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[2][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css', 'punctuation.definition.keyword.css'] - expect(lines[2][1]).toEqual value: 'annotation', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css'] - expect(lines[2][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[2][4]).toEqual value: 'ident', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[2][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[2][7]).toEqual value: '1', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[2][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[3][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css', 'punctuation.definition.keyword.css'] - expect(lines[3][1]).toEqual value: 'stylistic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css'] - expect(lines[3][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[3][4]).toEqual value: 'stylish', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[3][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[3][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[3][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[4][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css', 'punctuation.definition.keyword.css'] - expect(lines[4][1]).toEqual value: 'styleset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css'] - expect(lines[4][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[4][4]).toEqual value: 'sets', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[4][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[4][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: '3', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][11]).toEqual value: '4', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[4][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[5][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css', 'punctuation.definition.keyword.css'] - expect(lines[5][1]).toEqual value: 'character-variant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css'] - expect(lines[5][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[5][4]).toEqual value: 'charvar', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[5][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[5][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[5][9]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'matches feature-name rules case-insensitively', -> - lines = grammar.tokenizeLines """ - @sWASH{ swashy: 2; } - @ornaMENts{ ident: 2; } - @anNOTatION{ ident: 1; } - @styLISTic{ stylish: 2; } - @STYLEset{ sets: 2 3 4; } - @CHARacter-VARiant{ charvar: 2 } - """ - expect(lines[0][1]).toEqual value: 'sWASH', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] - expect(lines[1][1]).toEqual value: 'ornaMENts', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css'] - expect(lines[2][1]).toEqual value: 'anNOTatION', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css'] - expect(lines[3][1]).toEqual value: 'styLISTic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css'] - expect(lines[4][1]).toEqual value: 'STYLEset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css'] - expect(lines[5][1]).toEqual value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css'] - - it 'matches comments inside feature-name rules', -> - lines = grammar.tokenizeLines """ - @font-feature-values Font name 2 { - @swash{/* - ========*/swashy:/**/2;/**/} - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] - expect(lines[0][3]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] - expect(lines[1][1]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] - expect(lines[1][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][3]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][0]).toEqual value: '========', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css'] - expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][2]).toEqual value: 'swashy', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[2][3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][5]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][6]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][7]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[2][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[3][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'highlights escape sequences inside feature-names', -> - {tokens} = grammar.tokenizeLine('@swash{ s\\000077a\\73hy: 1; }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] - expect(tokens[4]).toEqual value: 's', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(tokens[5]).toEqual value: '\\000077', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css'] - expect(tokens[6]).toEqual value: 'a', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(tokens[7]).toEqual value: '\\73', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css'] - expect(tokens[8]).toEqual value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - - describe '@page', -> - it 'tokenises @page blocks correctly', -> - {tokens} = grammar.tokenizeLine('@page :first { }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[4]).toEqual value: 'first', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[5]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[8]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@page:right{}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] - expect(tokens[2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[3]).toEqual value: 'right', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@page{}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe '@counter-style', -> - it 'tokenises them and their contents correctly', -> - lines = grammar.tokenizeLines """ - @counter-style winners-list { - system: fixed; - symbols: url(gold-medal.svg) url(silver-medal.svg) url(bronze-medal.svg); - suffix: " "; - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] - expect(lines[0][3]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: 'system', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] - expect(lines[1][4]).toEqual value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] - expect(lines[2][1]).toEqual value: 'symbols', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][6]).toEqual value: 'gold-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] - expect(lines[2][7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][9]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[2][10]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][11]).toEqual value: 'silver-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] - expect(lines[2][12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][14]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[2][15]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][16]).toEqual value: 'bronze-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] - expect(lines[2][17]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][18]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] - expect(lines[3][1]).toEqual value: 'suffix', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] - expect(lines[3][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[3][6]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[3][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] - expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'matches injected comments', -> - {tokens} = grammar.tokenizeLine('@counter-style/*{*/winners-list/*}*/{ system: fixed; }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css'] - expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[9]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[11]).toEqual value: 'system', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[12]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] - expect(tokens[14]).toEqual value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] - expect(tokens[17]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "allows the counter-style's name to start on a different line", -> - lines = grammar.tokenizeLines """ - @counter-style - winners-list - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] - expect(lines[1][0]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - - it "highlights escape sequences inside the style's name", -> - {tokens} = grammar.tokenizeLine '@counter-style A\\01F602z' - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] - expect(tokens[3]).toEqual value: 'A', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - expect(tokens[4]).toEqual value: '\\01F602', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css', 'constant.character.escape.codepoint.css'] - expect(tokens[5]).toEqual value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - - describe '@document', -> - it 'correctly tokenises @document rules', -> - lines = grammar.tokenizeLines """ - @document url(http://www.w3.org/), - url-prefix(http://www.w3.org/Style/), /* Comment */ - domain(/**/mozilla.org), - regexp("https:.*") { - body{ color: #f00; } - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'document', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css'] - expect(lines[0][3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[0][4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[0][5]).toEqual value: 'http://www.w3.org/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'variable.parameter.url.css'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[0][7]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][1]).toEqual value: 'url-prefix', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] - expect(lines[1][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][3]).toEqual value: 'http://www.w3.org/Style/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'variable.parameter.document-rule.css'] - expect(lines[1][4]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][5]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][7]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][8]).toEqual value: ' Comment ', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css'] - expect(lines[1][9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][1]).toEqual value: 'domain', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] - expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][5]).toEqual value: 'mozilla.org', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'variable.parameter.document-rule.css'] - expect(lines[2][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][7]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][1]).toEqual value: 'regexp', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] - expect(lines[3][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[3][4]).toEqual value: 'https:.*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css'] - expect(lines[3][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[3][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][8]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.begin.bracket.curly.css'] - expect(lines[4][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[4][4]).toEqual value: 'color', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[4][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[4][7]).toEqual value: '#', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(lines[4][8]).toEqual value: 'f00', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] - expect(lines[4][9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][11]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[5][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css'] - - describe '@viewport', -> - it 'tokenises @viewport blocks correctly', -> - {tokens} = grammar.tokenizeLine('@viewport { min-width: 640px; max-width: 800px; }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'viewport', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: 'min-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[6]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[8]).toEqual value: '640', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[12]).toEqual value: 'max-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[13]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[15]).toEqual value: '800', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[16]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[17]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[19]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenises them across lines', -> - lines = grammar.tokenizeLines """ - @-O-VIEWPORT - { - zoom: 0.75; - min-zoom: 0.5; - max-zoom: 0.9; - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: '-O-VIEWPORT', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] - expect(lines[1][0]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[2][1]).toEqual value: 'zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: '0.75', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[3][1]).toEqual value: 'min-zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[3][4]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][1]).toEqual value: 'max-zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[4][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[4][4]).toEqual value: '0.9', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[5][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenises injected comments', -> - lines = grammar.tokenizeLines """ - @-ms-viewport/*{*/{/* - ==*/orientation: landscape; - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: '-ms-viewport', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] - expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css'] - expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css'] - expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][2]).toEqual value: 'orientation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[1][5]).toEqual value: 'landscape', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][6]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[2][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'unknown at-rules', -> - it 'correctly parses single-line unknown at-rules closing with semicolons', -> - lines = grammar.tokenizeLines """ - @foo; - @foo ; - @foo a; - @foo (); - @foo (a); - """ - expect(lines[0][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - expect(lines[1][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - expect(lines[2][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - expect(lines[2][2]).toEqual value: ' a', scopes: ['source.css', 'meta.at-rule.header.css'] - - expect(lines[3][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - expect(lines[3][2]).toEqual value: ' ()', scopes: ['source.css', 'meta.at-rule.header.css'] - - expect(lines[4][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - expect(lines[4][2]).toEqual value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css'] - - it 'correctly parses single-line unknown at-rules closing with ;', -> - lines = grammar.tokenizeLines """ - @foo bar; - .foo - """ - expect(lines[0][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - expect(lines[1][0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[1][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - describe 'capitalisation', -> - it 'ignores case in at-rules', -> - lines = grammar.tokenizeLines """ - @IMPoRT url("file.css"); - @MEdIA (MAX-WIDTH: 2px){ } - @pAgE :fIRST { } - @NAMEspace "A"; - @foNT-FacE {} - """ - expect(lines[0][1]).toEqual value: 'IMPoRT', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(lines[1][1]).toEqual value: 'MEdIA', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(lines[1][4]).toEqual value: 'MAX-WIDTH', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(lines[2][1]).toEqual value: 'pAgE', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] - expect(lines[2][4]).toEqual value: 'fIRST', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[3][1]).toEqual value: 'NAMEspace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(lines[4][1]).toEqual value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css'] - - it 'ignores case in property names', -> - lines = grammar.tokenizeLines """ - a{ COLOR: #fff; } - a{ gRId-tEMPLaTe: none; } - a{ bACkgrOUND-iMAGE: none; } - a{ -MOZ-IMAGE: none; } - """ - expect(lines[0][3]).toEqual value: 'COLOR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][3]).toEqual value: 'gRId-tEMPLaTe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][3]).toEqual value: 'bACkgrOUND-iMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][3]).toEqual value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - - it 'ignores case in property keywords', -> - lines = grammar.tokenizeLines """ - a{ color: INItIaL; } - a{ color: trAnsPAREnT; } - a{ color: rED; } - a{ color: unSET; } - a{ color: NONe; } - a{ style: lOWER-lATIN; } - a{ color: -WebkIT-foo; } - a{ font: HelVETica; } - """ - expect(lines[0][6]).toEqual value: 'INItIaL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][6]).toEqual value: 'trAnsPAREnT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[2][6]).toEqual value: 'rED', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[3][6]).toEqual value: 'unSET', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[4][6]).toEqual value: 'NONe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[5][6]).toEqual value: 'lOWER-lATIN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css'] - expect(lines[6][6]).toEqual value: '-WebkIT-foo', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] - expect(lines[7][6]).toEqual value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] - - it 'ignores case in selectors', -> - lines = grammar.tokenizeLines """ - DIV:HOVER { } - #id::BefORE { } - #id::aFTEr { } - TABle:nTH-cHILD(2N+1) {} - htML:NOT(.htiml) {} - I::BACKDROP - I::-mOZ-thing {} - """ - expect(lines[0][0]).toEqual value: 'DIV', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[0][2]).toEqual value: 'HOVER', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[1][3]).toEqual value: 'BefORE', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[2][3]).toEqual value: 'aFTEr', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[3][0]).toEqual value: 'TABle', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[3][2]).toEqual value: 'nTH-cHILD', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[3][4]).toEqual value: '2N+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(lines[4][0]).toEqual value: 'htML', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][2]).toEqual value: 'NOT', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[5][0]).toEqual value: 'I', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[5][2]).toEqual value: 'BACKDROP', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[6][2]).toEqual value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - it 'ignores case in function names', -> - lines = grammar.tokenizeLines """ - a{ color: RGBa(); } - a{ color: hslA(); } - a{ color: URL(); } - a{ content: ATTr(); } - a{ content: CoUNTer(); } - a{ content: cuBIC-beZIER()} - a{ content: sTePs()} - a{ content: cALc(2 + 2)} - """ - expect(lines[0][6]).toEqual value: 'RGBa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[1][6]).toEqual value: 'hslA', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[2][6]).toEqual value: 'URL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[3][6]).toEqual value: 'ATTr', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[4][6]).toEqual value: 'CoUNTer', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[5][6]).toEqual value: 'cuBIC-beZIER', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] - expect(lines[6][6]).toEqual value: 'sTePs', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] - expect(lines[7][6]).toEqual value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] - - it 'ignores case in unit names', -> - lines = grammar.tokenizeLines """ - a{width: 20EM; } - a{width: 20ReM; } - a{width: 8tURN; } - a{width: 20S; } - a{width: 20CM} - a{width: 2gRAd} - """ - expect(lines[0][5]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[0][6]).toEqual value: 'EM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[1][6]).toEqual value: 'ReM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.rem.css'] - expect(lines[2][2]).toEqual value: 'width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][6]).toEqual value: 'tURN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.turn.css'] - expect(lines[3][6]).toEqual value: 'S', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.s.css'] - expect(lines[4][5]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][6]).toEqual value: 'CM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css'] - expect(lines[5][6]).toEqual value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css'] - - describe 'pseudo-classes', -> - it 'tokenizes regular pseudo-classes', -> - {tokens} = grammar.tokenizeLine 'p:first-child' - expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - - it "doesn't tokenise pseudo-classes if followed by a semicolon or closed bracket", -> - {tokens} = grammar.tokenizeLine('p{ left:left }') - expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[5]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe ':dir()', -> - it 'tokenises :dir() and its keywords', -> - lines = grammar.tokenizeLines """ - a:dir(ltr ){ } - *:dir( rtl){ } - """ - expect(lines[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][2]).toEqual value: 'dir', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[0][4]).toEqual value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] - expect(lines[0][5]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(lines[1][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[1][2]).toEqual value: 'dir', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[1][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][4]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] - expect(lines[1][5]).toEqual value: 'rtl', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] - expect(lines[1][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'allows :dir() to include comments and newlines', -> - lines = grammar.tokenizeLines """ - :DIR(/** - ==*/ltr/* - */) - """ - expect(lines[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][1]).toEqual value: 'DIR', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[0][3]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][4]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][2]).toEqual value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] - expect(lines[1][3]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][0]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][1]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - describe ':lang()', -> - it 'tokenizes :lang()', -> - {tokens} = grammar.tokenizeLine ':lang(zh-Hans-CN,es-419)' - expect(tokens[0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[3]).toEqual value: 'zh-Hans-CN', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css'] - expect(tokens[4]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(tokens[5]).toEqual value: 'es-419', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'does not tokenize unquoted language ranges containing asterisks', -> - {tokens} = grammar.tokenizeLine ':lang(zh-*-CN)' - expect(tokens[3]).toEqual value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css'] - - it 'tokenizes language ranges containing asterisks quoted as strings', -> - {tokens} = grammar.tokenizeLine ':lang("zh-*-CN",\'*-ab-\')' - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'support.constant.language-range.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[6]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(tokens[7]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '*-ab-', scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'support.constant.language-range.css'] - expect(tokens[9]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - - describe ':not()', -> - it 'tokenises other selectors inside :not()', -> - {tokens} = grammar.tokenizeLine('*:not(.class-name):not(div) {}') - expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[5]).toEqual value: 'class-name', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[8]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[10]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'tokenises injected comments', -> - {tokens} = grammar.tokenizeLine('*:not(/*(*/.class-name/*)*/):not(/*b*/) {}') - expect(tokens[2]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(tokens[6]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[7]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[8]).toEqual value: 'class-name', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[13]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[14]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[15]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[16]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[17]).toEqual value: 'b', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(tokens[18]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[19]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - describe ':nth-*()', -> - it 'tokenizes :nth-child()', -> - tokens = grammar.tokenizeLines ''' - :nth-child(2n+1) - :nth-child(2n -1) - :nth-child(-2n+ 1) - :nth-child(-2n - 1) - :nth-child(odd) - :nth-child(even) - :nth-child( odd ) - :nth-child( even ) - ''' - expect(tokens[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[0][1]).toEqual value: 'nth-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[0][3]).toEqual value: '2n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[0][4]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[1][3]).toEqual value: '2n -1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][3]).toEqual value: '-2n+ 1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[3][3]).toEqual value: '-2n - 1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[4][3]).toEqual value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - expect(tokens[5][3]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - expect(tokens[6][3]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[6][4]).toEqual value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - expect(tokens[7][4]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - expect(tokens[7][5]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] - - it 'tokenizes :nth-last-child()', -> - tokens = grammar.tokenizeLines ''' - :nth-last-child(2n) - :nth-last-child( -2n) - :nth-last-child( 2n ) - :nth-last-child(even) - ''' - expect(tokens[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[0][1]).toEqual value: 'nth-last-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[0][3]).toEqual value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[0][4]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[1][4]).toEqual value: '-2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][4]).toEqual value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[3][3]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - - it 'tokenizes :nth-of-type()', -> - tokens = grammar.tokenizeLines ''' - img:nth-of-type(+n+1) - img:nth-of-type(-n+1) - img:nth-of-type(n+1) - ''' - expect(tokens[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[0][2]).toEqual value: 'nth-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[0][4]).toEqual value: '+n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[0][5]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[1][4]).toEqual value: '-n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][4]).toEqual value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - - it 'tokenizes ::nth-last-of-type()', -> - tokens = grammar.tokenizeLines ''' - h1:nth-last-of-type(-1) - h1:nth-last-of-type(+2) - h1:nth-last-of-type(3) - ''' - expect(tokens[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[0][2]).toEqual value: 'nth-last-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[0][4]).toEqual value: '-1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[0][5]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[1][4]).toEqual value: '+2', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][4]).toEqual value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - - describe 'pseudo-elements', -> - # :first-line, :first-letter, :before and :after - it 'tokenizes both : and :: notations for pseudo-elements introduced in CSS 1 and 2', -> - {tokens} = grammar.tokenizeLine '.opening:first-letter' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'opening', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[3]).toEqual value: 'first-letter', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - {tokens} = grammar.tokenizeLine 'q::after' - expect(tokens[0]).toEqual value: 'q', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - it 'tokenizes both : and :: notations for vendor-prefixed pseudo-elements', -> - {tokens} = grammar.tokenizeLine ':-ms-input-placeholder' - expect(tokens[0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-ms-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - {tokens} = grammar.tokenizeLine '::-webkit-input-placeholder' - expect(tokens[0]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - it 'only tokenizes the :: notation for other pseudo-elements', -> - {tokens} = grammar.tokenizeLine '::selection' - expect(tokens[0]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - {tokens} = grammar.tokenizeLine ':selection' - expect(tokens[0]).toEqual value: ':selection', scopes: ['source.css', 'meta.selector.css'] - - describe 'compound selectors', -> - it 'tokenizes the combination of type selectors followed by class selectors', -> - {tokens} = grammar.tokenizeLine 'very-custom.class' - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - it 'tokenizes the combination of type selectors followed by pseudo-classes', -> - {tokens} = grammar.tokenizeLine 'very-custom:hover' - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - - it 'tokenizes the combination of type selectors followed by pseudo-elements', -> - {tokens} = grammar.tokenizeLine 'very-custom::shadow' - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - describe 'property lists (declaration blocks)', -> - it 'tokenizes inline property lists', -> - {tokens} = grammar.tokenizeLine 'div { font-size: inherit; }' - expect(tokens[4]).toEqual value: 'font-size', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[7]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes compact inline property lists', -> - {tokens} = grammar.tokenizeLine 'div{color:inherit;float:left}' - expect(tokens[2]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[4]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[6]).toEqual value: 'float', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[8]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes multiple inline property lists', -> - tokens = grammar.tokenizeLines ''' - very-custom { color: inherit } - another-one { display : none ; } - ''' - expect(tokens[0][0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[0][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][7]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[1][0]).toEqual value: 'another-one', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1][4]).toEqual value: 'display', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[1][5]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[1][8]).toEqual value: 'none', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[1][9]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[1][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[1][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes custom properties', -> - {tokens} = grammar.tokenizeLine ':root { --white: #FFF; }' - expect(tokens[5]).toEqual value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css'] - - it 'tokenises commas between property values', -> - {tokens} = grammar.tokenizeLine('a{ text-shadow: a, b; }') - expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - - it 'tokenises superfluous semicolons', -> - lines = grammar.tokenizeLines ''' - .test{ width: 20em;;;;;;;;; - ;;;;;;;;;height: 10em; } - ''' - for i in [0..8] - expect(lines[0][i+9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[1][i]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[1][9]).toEqual value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - - describe 'values', -> - it 'tokenizes color keywords', -> - {tokens} = grammar.tokenizeLine '#jon { color: snow; }' - expect(tokens[8]).toEqual value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css'] - - it 'tokenises RGBA values in hex notation', -> - {tokens} = grammar.tokenizeLine('p{ color: #f030; }') - expect(tokens[6]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(tokens[7]).toEqual value: 'f030', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{ color: #CAFEBABE; }') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(tokens[7]).toEqual value: 'CAFEBABE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{ color: #CAFEBABEF; }') - expect(tokens[6]).toEqual value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - - it 'tokenizes common font names', -> - {tokens} = grammar.tokenizeLine 'p { font-family: Verdana, Helvetica, sans-serif; }' - expect(tokens[7]).toEqual value: 'Verdana', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] - expect(tokens[10]).toEqual value: 'Helvetica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] - expect(tokens[13]).toEqual value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] - - it 'tokenizes predefined list style types', -> - {tokens} = grammar.tokenizeLine 'ol.myth { list-style-type: cjk-earthly-branch }' - expect(tokens[9]).toEqual value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css'] - - it 'tokenizes numeric values', -> - {tokens} = grammar.tokenizeLine 'div { font-size: 14px; }' - expect(tokens[7]).toEqual value: '14', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - - it 'does not tokenize invalid numeric values', -> - {tokens} = grammar.tokenizeLine 'div { font-size: test14px; }' - expect(tokens[7]).toEqual value: 'test14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - - {tokens} = grammar.tokenizeLine 'div { font-size: test-14px; }' - expect(tokens[7]).toEqual value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - - it 'tokenizes vendor-prefixed values', -> - {tokens} = grammar.tokenizeLine '.edge { cursor: -webkit-zoom-in; }' - expect(tokens[8]).toEqual value: '-webkit-zoom-in', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] - - {tokens} = grammar.tokenizeLine '.edge { width: -moz-min-content; }' - expect(tokens[8]).toEqual value: '-moz-min-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] - - {tokens} = grammar.tokenizeLine '.edge { display: -ms-grid; }' - expect(tokens[8]).toEqual value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] - - it 'tokenizes custom variables', -> - {tokens} = grammar.tokenizeLine 'div { color: var(--primary-color) }' - expect(tokens[9]).toEqual value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - - it 'tokenises numeric values correctly', -> - lines = grammar.tokenizeLines """ - .a { a: 12em } - .a { a: 4.01ex } - .a { a: -456.8ch } - .a { a: 0.0REM } - .a { a: +0.0vh } - .a { a: -0.0vw } - .a { a: .6px } - .a { a: 10e3mm } - .a { a: 10E3cm } - .a { a: -3.4e+2In } - .a { a: -3.4e-2ch } - .a { a: +.5E-2% } - .a { a: -3.4e-2% } - """ - expect(lines[0][8]).toEqual value: '12', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[0][9]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[1][8]).toEqual value: '4.01', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][9]).toEqual value: 'ex', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ex.css'] - expect(lines[2][8]).toEqual value: '-456.8', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][9]).toEqual value: 'ch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ch.css'] - expect(lines[3][8]).toEqual value: '0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][9]).toEqual value: 'REM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.rem.css'] - expect(lines[4][8]).toEqual value: '+0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: 'vh', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.vh.css'] - expect(lines[5][8]).toEqual value: '-0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[5][9]).toEqual value: 'vw', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.vw.css'] - expect(lines[6][8]).toEqual value: '.6', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[6][9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[7][8]).toEqual value: '10e3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[7][9]).toEqual value: 'mm', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.mm.css'] - expect(lines[8][8]).toEqual value: '10E3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[8][9]).toEqual value: 'cm', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css'] - expect(lines[9][8]).toEqual value: '-3.4e+2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[9][9]).toEqual value: 'In', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.in.css'] - expect(lines[10][8]).toEqual value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[10][9]).toEqual value: 'ch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ch.css'] - expect(lines[11][8]).toEqual value: '+.5E-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[11][9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[12][8]).toEqual value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[12][9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - - describe 'functional notation', -> - describe 'attr()', -> - it 'tokenises parameters correctly and case-insensitively', -> - {tokens} = grammar.tokenizeLine('a{content:aTTr(data-width px, inherit)}') - expect(tokens[4]).toEqual value: 'aTTr', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: 'data-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.constant.property-value.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[13]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'matches variables', -> - {tokens} = grammar.tokenizeLine('a{content:ATTR(VAR(--name) px, "N/A")}') - expect(tokens[4]).toEqual value: 'ATTR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: 'VAR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[11]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(tokens[12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] - expect(tokens[14]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[15]).toEqual value: 'N/A', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] - expect(tokens[16]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[17]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - - describe 'calc()', -> - it 'tokenises calculations', -> - lines = grammar.tokenizeLines """ - a{ - width: calc(3px + -1em); - width: calc(3px - -1em); - width: calc(3px * 2); - width: calc(3px / 2); - } - """ - expect(lines[1][4]).toEqual value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: '3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(lines[1][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[1][9]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(lines[1][11]).toEqual value: '-1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(lines[1][12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[1][13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][9]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(lines[2][11]).toEqual value: '-1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(lines[2][12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[3][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[3][9]).toEqual value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(lines[4][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[4][9]).toEqual value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(lines[4][11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - - it 'requires whitespace around + and - operators', -> - {tokens} = grammar.tokenizeLine('a{ width: calc(3px+1em); }') - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] - expect(tokens[11]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(tokens[12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - - {tokens} = grammar.tokenizeLine('a{ width: calc(3px--1em); height: calc(10-1em);}') - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: '--1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] - expect(tokens[19]).toEqual value: '10', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(tokens[20]).toEqual value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] - - it 'does not require whitespace around * and / operators', -> - {tokens} = grammar.tokenizeLine('a{ width: calc(3px*2); }') - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(tokens[11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - - {tokens} = grammar.tokenizeLine('a{ width: calc(3px/2); }') - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(tokens[11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - - it 'matches variable expansions inside calculations', -> - {tokens} = grammar.tokenizeLine('.foo { margin-top: calc(var(--gap) + 1px); }') - expect(tokens[8]).toEqual value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[10]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[11]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[12]).toEqual value: '--gap', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[15]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(tokens[17]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(tokens[18]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[19]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[20]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[22]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'colours', -> - it 'tokenises colour functions correctly', -> - {tokens} = grammar.tokenizeLine('a{ color: rgb(187,255,221); }') - expect(tokens[6]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '187', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[10]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[12]).toEqual value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('a{ color: RGBa( 100%, 0% ,20.17% ,.5 ); }') - expect(tokens[6]).toEqual value: 'RGBa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[9]).toEqual value: '100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[10]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[13]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[14]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[17]).toEqual value: '20.17', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[18]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[20]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[21]).toEqual value: '.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[23]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('a{color:HSL(0, 00100%,50%)}') - expect(tokens[4]).toEqual value: 'HSL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[9]).toEqual value: '00100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[10]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[12]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[13]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('a{color:HSLa(2,.0%,1%,.7)}') - expect(tokens[4]).toEqual value: 'HSLa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[8]).toEqual value: '.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[12]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[13]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[14]).toEqual value: '.7', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'matches variables as colour components', -> - {tokens} = grammar.tokenizeLine('a{ color: RGBA(var(--red), 0% , 20%, .2)}') - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[10]).toEqual value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - - it 'matches comments between colour components', -> - {tokens} = grammar.tokenizeLine('a{ color: rgba(/**/255/*=*/,0,/*2.2%*/51/*,*/0.2)}') - expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[10]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[11]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[12]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(tokens[13]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[14]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[17]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[19]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[20]).toEqual value: '51', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[21]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[22]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(tokens[23]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[24]).toEqual value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - - it 'allows colour components to be split across lines', -> - lines = grammar.tokenizeLines """ - .frost{ - background-color: rgba( - var(--red), /* Red */ - var(--green), /* Green */ - var(--blue), /* Blue */ - /* var(--test), - /**/var(--opacity) /* Transparency */ - ); - } - """ - expect(lines[1][4]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][3]).toEqual value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(lines[2][4]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][8]).toEqual value: ' Red ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[3][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(lines[3][3]).toEqual value: '--green', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(lines[3][5]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][8]).toEqual value: ' Green ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[4][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(lines[4][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][3]).toEqual value: '--blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(lines[4][4]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][5]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][8]).toEqual value: ' Blue ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[4][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[5][1]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[5][2]).toEqual value: ' var(--test),', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[6][0]).toEqual value: ' /*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[6][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[6][2]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(lines[6][3]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[6][4]).toEqual value: '--opacity', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(lines[6][5]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[6][7]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[6][8]).toEqual value: ' Transparency ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[6][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[7][1]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - describe 'gradients', -> - it 'tokenises linear gradients', -> - {tokens} = grammar.tokenizeLine('a{ background-image: linear-gradient( 45deg, blue, red ); }') - expect(tokens[6]).toEqual value: 'linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[9]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[10]).toEqual value: 'deg', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.deg.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[13]).toEqual value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(tokens[14]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[16]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[19]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('a{ background-image: LINear-graDIEnt( ellipse to left top, blue, red);') - expect(tokens[6]).toEqual value: 'LINear-graDIEnt', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(tokens[9]).toEqual value: 'ellipse', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(tokens[11]).toEqual value: 'to', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] - expect(tokens[13]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(tokens[15]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[18]).toEqual value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(tokens[19]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[21]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] - - it 'tokenises radial gradients', -> - {tokens} = grammar.tokenizeLine('a{ background-image: radial-gradient(farthest-corner at 45px 45px , #f00 0%, #00f 100%);}') - expect(tokens[6]).toEqual value: 'radial-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: 'farthest-corner', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(tokens[10]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] - expect(tokens[12]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[13]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[15]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[16]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[20]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(tokens[21]).toEqual value: 'f00', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - expect(tokens[23]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[24]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - - {tokens} = grammar.tokenizeLine('a{ background-image: RADial-gradiENT(16px at 60px 50%,#000 0%, #000 14px, rgba(0,0,0,.3) 18px, transparent 19px)}') - expect(tokens[6]).toEqual value: 'RADial-gradiENT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '16', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[11]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] - expect(tokens[13]).toEqual value: '60', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[14]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[16]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[17]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[19]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(tokens[20]).toEqual value: '000', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - expect(tokens[33]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[34]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[35]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[36]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[41]).toEqual value: '.3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[42]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[48]).toEqual value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - - it 'matches gradients that span multiple lines with injected comments', -> - lines = grammar.tokenizeLines """ - a{ - background-image: raDIAL-gradiENT( - ellipse farthest-corner/*@*/at/*@*/470px 47px,/*=== - ========*/#FFFF80 20%, rgba(204, 153, 153, 0.4) 30%,/*))))))))}*/#E6E6FF 60%); } - """ - expect(lines[1][4]).toEqual value: 'raDIAL-gradiENT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(lines[2][1]).toEqual value: 'ellipse', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(lines[2][3]).toEqual value: 'farthest-corner', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][5]).toEqual value: '@', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[2][6]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][7]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] - expect(lines[2][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][11]).toEqual value: '470', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(lines[2][12]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[2][16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][17]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][18]).toEqual value: '===', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[3][0]).toEqual value: '========', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[3][2]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(lines[3][3]).toEqual value: 'FFFF80', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - expect(lines[3][9]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[3][10]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][20]).toEqual value: '0.4', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[3][21]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][26]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][27]).toEqual value: '))))))))}', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[3][28]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[3][29]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(lines[3][30]).toEqual value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - - it 'highlights vendored gradient functions', -> - lines = grammar.tokenizeLines """ - .grad { - background-image: -webkit-linear-gradient(top, /* For Chrome 25 and Safari 6, iOS 6.1, Android 4.3 */ hsl(0, 80%, 70%), #bada55); - background-image: -moz-linear-gradient(top, /* For Firefox (3.6 to 15) */ hsl(0, 80%, 70%), #bada55); - background-image: -o-linear-gradient(top, /* For old Opera (11.1 to 12.0) */ hsl(0, 80%, 70%), #bada55); - } - """ - expect(lines[1][4]).toEqual value: '-webkit-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(lines[1][10]).toEqual value: ' For Chrome 25 and Safari 6, iOS 6.1, Android 4.3 ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[1][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[1][22]).toEqual value: '70', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][23]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[1][24]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][27]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(lines[1][28]).toEqual value: 'bada55', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - expect(lines[1][29]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][4]).toEqual value: '-moz-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][6]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(lines[2][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][10]).toEqual value: ' For Firefox (3.6 to 15) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[2][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[2][14]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][24]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][29]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][4]).toEqual value: '-o-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(lines[3][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][10]).toEqual value: ' For old Opera (11.1 to 12.0) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[3][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[3][14]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - - it 'highlights antique Webkit syntax as deprecated', -> - lines = grammar.tokenizeLines """ - .grad { - background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, - from( rgb(0, 171, 235)), - color-stop(0.5, rgb(255, 255, 255)), - color-stop(0.5, rgb(102, 204, 0)), - to(rgb(255, 255, 255))), - -webkit-gradient(radial, 45 45, 10, 52 50, 30, from(#A7D30C), to(rgba(1,159,98,0)), color-stop(90%, #019F62)), - -webkit-gradient(radial, 105 105, 20, 112 120, 50, from(#ff5f98), to(rgba(255,1,136,0)), color-stop(75%, #ff0188)), - -webkit-gradient(radial, 95 15, 15, 102 20, 40, from(#00c9ff), to(rgba(0,201,255,0)), color-stop(80%, #00b5e2)), - -webkit-gradient(radial, 0 150, 50, 0 140, 90, from(#f4f201), to(rgba(228, 199,0,0)), color-stop(80%, #e4c700)); - } - """ - expect(lines[1][4]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: 'linear', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] - expect(lines[1][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][19]).toEqual value: '100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[1][20]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[2][1]).toEqual value: 'from', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] - expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][4]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][9]).toEqual value: '171', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[2][10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][1]).toEqual value: 'color-stop', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] - expect(lines[3][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][3]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[3][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][16]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][17]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][1]).toEqual value: 'color-stop', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] - expect(lines[4][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][3]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[4][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][6]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[4][7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][8]).toEqual value: '102', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][11]).toEqual value: '204', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[4][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][14]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[4][15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][16]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][17]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[5][1]).toEqual value: 'to', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] - expect(lines[5][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[5][12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[5][13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[5][14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[5][15]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(lines[6][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] - expect(lines[6][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[6][3]).toEqual value: 'radial', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] - expect(lines[6][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[6][8]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[6][31]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[7][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] - expect(lines[7][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[9][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] - expect(lines[9][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[9][3]).toEqual value: 'radial', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] - expect(lines[9][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[9][6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[9][8]).toEqual value: '150', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[9][54]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[9][55]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[10][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'other functions', -> - it 'tokenises basic-shape functions', -> - lines = grammar.tokenizeLines """ - a{ - shape-outside: circle(20em/*=*/at 50% 50%); - shape-outside: inset(1em, 1em, 1em, 1em); - } - """ - expect(lines[1][4]).toEqual value: 'circle', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'support.function.shape.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[1][7]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[1][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][9]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css'] - expect(lines[1][10]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][11]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'keyword.operator.shape.css'] - expect(lines[1][13]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[1][14]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[1][16]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[1][17]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[1][18]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][4]).toEqual value: 'inset', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'support.function.shape.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][6]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[2][7]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[2][8]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][10]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[2][11]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[2][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][14]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[2][15]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[2][16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][18]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[2][19]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[2][20]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'tokenises OpenType feature functions', -> - lines = grammar.tokenizeLines """ - .font{ - font-variant-alternates: stylistic(user-defined-ident); - font-variant-alternates: styleset(user-defined-ident); - font-variant-alternates: character-variant(user-defined-ident); - font-variant-alternates: swash(user-defined-ident); - font-variant-alternates: ornaments(user-defined-ident); - font-variant-alternates: annotation(user-defined-ident); - font-variant-alternates: swash(ident1) annotation(ident2); - } - """ - expect(lines[1][4]).toEqual value: 'stylistic', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[1][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][4]).toEqual value: 'styleset', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[2][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][4]).toEqual value: 'character-variant', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[3][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[3][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][4]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[4][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[4][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[5][4]).toEqual value: 'ornaments', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[5][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[5][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[5][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[6][4]).toEqual value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[6][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[6][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[6][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[7][4]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[7][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[7][6]).toEqual value: 'ident1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[7][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[7][9]).toEqual value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[7][10]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[7][11]).toEqual value: 'ident2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[7][12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'tokenises image-set()', -> - lines = grammar.tokenizeLines """ - a{ - background-image: image-set( "foo.png" 1x, - "foo-2x.png" 2x, - "foo-print.png" 600dpi ); - } - """ - expect(lines[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[0][1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: 'background-image', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[1][4]).toEqual value: 'image-set', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][8]).toEqual value: 'foo.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] - expect(lines[1][9]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[1][11]).toEqual value: '1x', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.other.density.css'] - expect(lines[1][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[2][2]).toEqual value: 'foo-2x.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] - expect(lines[2][3]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[2][5]).toEqual value: '2x', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.other.density.css'] - expect(lines[2][6]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[3][2]).toEqual value: 'foo-print.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] - expect(lines[3][3]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[3][5]).toEqual value: '600', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css'] - expect(lines[3][6]).toEqual value: 'dpi', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css', 'keyword.other.unit.dpi.css'] - expect(lines[3][8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'timing-functions', -> - it 'tokenises them correctly', -> - {tokens} = grammar.tokenizeLine('a{ zoom: cubic-bezier(/**/1.2,/*=*/0,0,0/**/)}') - expect(tokens[6]).toEqual value: 'cubic-bezier', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[10]).toEqual value: '1.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[15]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] - expect(tokens[17]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] - expect(tokens[19]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[20]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[21]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[22]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'highlights the "start" and "end" keywords', -> - {tokens} = grammar.tokenizeLine('a{ before: steps(0, start); after: steps(1, end); }') - expect(tokens[6]).toEqual value: 'steps', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: 'start', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[23]).toEqual value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css'] - - describe 'variables', -> - it 'scopes var() statements as variables', -> - {tokens} = grammar.tokenizeLine('a{color: var(--name)}') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[2]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[5]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[7]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{color: var( --name )}') - expect(tokens[5]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'allows injected comments', -> - {tokens} = grammar.tokenizeLine('a{ color: var( /*=*/ --something ) }') - expect(tokens[6]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[10]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css'] - expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[13]).toEqual value: '--something', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'tokenises fallback values', -> - {tokens} = grammar.tokenizeLine('.bar{ width: var(--page-width, /*;;;);*/ 2); }') - expect(tokens[7]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[8]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[9]).toEqual value: '--page-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.separator.list.comma.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: ';;;);', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[16]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'constant.numeric.css'] - expect(tokens[17]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[18]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - - it 'does not tokenise functions with whitespace between name and parameters', -> - {tokens} = grammar.tokenizeLine('a{ p: attr (title); }') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'p', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'attr (title', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{url:url (s)}') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[2]).toEqual value: 'url', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[4]).toEqual value: 'url (s', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[5]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{content:url ("http://github.com/");}') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[2]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[4]).toEqual value: 'url (', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'http://github.com/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{content: url (http://a.pl/)}') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[2]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[5]).toEqual value: 'url (http://a.pl/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{ color: rgb (187,255,221); }') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'rgb (', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[7]).toEqual value: '187', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(tokens[9]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[13]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[15]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'Unicode ranges', -> - it 'tokenises single codepoints', -> - {tokens} = grammar.tokenizeLine('a{ a: U+A5 }') - expect(tokens[6]).toEqual value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - it 'tokenises codepoint ranges', -> - {tokens} = grammar.tokenizeLine('a{ a: U+0025-00FF }') - expect(tokens[6]).toEqual value: 'U+0025', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] - expect(tokens[8]).toEqual value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - {tokens} = grammar.tokenizeLine('a{ unicode-range: u+0-7F }') - expect(tokens[6]).toEqual value: 'u+0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] - expect(tokens[8]).toEqual value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - it 'tokenises wildcard ranges', -> - {tokens} = grammar.tokenizeLine('a{ unicode-range: U+4?? }') - expect(tokens[6]).toEqual value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - {tokens} = grammar.tokenizeLine('a{ unicode-range: U+0025-00FF, U+4?? }') - expect(tokens[6]).toEqual value: 'U+0025', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] - expect(tokens[8]).toEqual value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - describe 'escape sequences', -> - it 'tokenizes escape sequences in single-quoted strings', -> - {tokens} = grammar.tokenizeLine "very-custom { content: '\\c0ffee' }" - - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[4]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[7]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css'] - - it 'tokenizes escape sequences in double-quoted strings', -> - {tokens} = grammar.tokenizeLine 'very-custom { content: "\\c0ffee" }' - - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[4]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css'] - - it 'tokenises escape sequences in selectors', -> - {tokens} = grammar.tokenizeLine('\\61 \\{ { } \\}') - expect(tokens[0]).toEqual value: '\\61', scopes: ['source.css', 'constant.character.escape.codepoint.css'] - expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'constant.character.escape.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[8]).toEqual value: '\\}', scopes: ['source.css', 'constant.character.escape.css'] - - {tokens} = grammar.tokenizeLine('\\61\\ \\. \\@media {}') # Matches <.><@media> - expect(tokens[0]).toEqual value: '\\61', scopes: ['source.css', 'constant.character.escape.codepoint.css'] - expect(tokens[1]).toEqual value: '\\ ', scopes: ['source.css', 'constant.character.escape.css'] - expect(tokens[2]).toEqual value: '\\.', scopes: ['source.css', 'constant.character.escape.css'] - expect(tokens[4]).toEqual value: '\\@', scopes: ['source.css', 'constant.character.escape.css'] - expect(tokens[5]).toEqual value: 'media', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[7]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises escape sequences in property lists', -> - {tokens} = grammar.tokenizeLine('a { \\77\\69\\64\\74\\68: 20px; }') # Same as writing "width: 20px" - expect(tokens[4]).toEqual value: '\\77', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[5]).toEqual value: '\\69', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[6]).toEqual value: '\\64', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[7]).toEqual value: '\\74', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[8]).toEqual value: '\\68', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[9]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - - it 'tokenises escape sequences in property values', -> - {tokens} = grammar.tokenizeLine('a { content: \\1F764; }') - expect(tokens[7]).toEqual value: '\\1F764', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.character.escape.codepoint.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'unclosed strings', -> - it 'highlights an unterminated string as an error', -> - {tokens} = grammar.tokenizeLine("a{ content: 'aaaa") - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[7]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] - - {tokens} = grammar.tokenizeLine('a{ content: "aaaa') - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[7]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] - - it "knows when a string is line-wrapped", -> - lines = grammar.tokenizeLines """ - a{ - content: "aaaaa\\\\\\ - aaa"; color: red; - } - """ - expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][5]).toEqual value: 'aaaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[1][6]).toEqual value: '\\\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.css'] - expect(lines[1][7]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.newline.css'] - expect(lines[2][0]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[2][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[2][2]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[2][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - - lines = grammar.tokenizeLines """ - a{ - content: 'aaaaa\\\\\\ - aaa'; color: red; - } - """ - expect(lines[1][4]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][5]).toEqual value: 'aaaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css'] - expect(lines[1][6]).toEqual value: '\\\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.css'] - expect(lines[1][7]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.newline.css'] - expect(lines[2][0]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css'] - expect(lines[2][1]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(lines[2][2]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[2][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - - it 'highlights escape sequences inside invalid strings', -> - {tokens} = grammar.tokenizeLine('a{ content: "aaa\\"aa') - expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[7]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] - expect(tokens[8]).toEqual value: '\\"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css'] - expect(tokens[9]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] - - {tokens} = grammar.tokenizeLine("a{ content: 'aaa\\'aa") - expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[7]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] - expect(tokens[8]).toEqual value: "\\'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css'] - expect(tokens[9]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] - - it 'highlights unclosed lines in line-wrapped strings', -> - lines = grammar.tokenizeLines """ - a{ - content: "aaa\\"aa\\ - aaaa - aaaa; color: red; - } - """ - expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][5]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[1][6]).toEqual value: '\\"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.css'] - expect(lines[1][7]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[1][8]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.newline.css'] - expect(lines[2][0]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] - expect(lines[3][0]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(lines[3][1]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[3][3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[3][6]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[3][7]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'comments', -> - it 'tokenises comments inside @import statements', -> - {tokens} = grammar.tokenizeLine('@import /* url("name"); */ "1.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[4]).toEqual value: ' url("name"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[5]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import/*";"*/ url("2.css");') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '";"', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[6]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[9]).toEqual value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[10]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import url("3.css") print /* url(";"); */;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: '3.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[10]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'tokenises comments inside @font-face statements', -> - {tokens} = grammar.tokenizeLine('@font-face/*"{;}"*/{}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'font-face', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '"{;}"', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes comments before media queries', -> - {tokens} = grammar.tokenizeLine '/* comment */ @media' - - expect(tokens[0]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[1]).toEqual value: ' comment ', scopes: ['source.css', 'comment.block.css'] - expect(tokens[2]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[4]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[5]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - - it 'tokenizes comments after media queries', -> - {tokens} = grammar.tokenizeLine '@media/* comment */ ()' - - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - - it 'tokenizes comments inside query lists', -> - {tokens} = grammar.tokenizeLine '@media (max-height: 40em/* comment */)' - - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'max-height', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[7]).toEqual value: '40', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[10]).toEqual value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - - it 'tokenizes inline comments', -> - {tokens} = grammar.tokenizeLine 'section {border:4px/*padding:1px*/}' - - expect(tokens[0]).toEqual value: 'section', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'border', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[5]).toEqual value: '4', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[6]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[7]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[8]).toEqual value: 'padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] - expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes multi-line comments', -> - lines = grammar.tokenizeLines """ - section { - border:4px /*1px; - padding:1px*/ - } - """ - - expect(lines[1][5]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(lines[1][6]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][7]).toEqual value: '1px;', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] - - expect(lines[2][0]).toEqual value: ' padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] - expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - - expect(lines[3][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'Animations', -> - it 'does not confuse animation names with predefined keywords', -> - tokens = grammar.tokenizeLines ''' - .animated { - animation-name: orphan-black; - animation-name: line-scale; - } - ''' - expect(tokens[1][4]).toEqual value: 'orphan-black', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[2][4]).toEqual value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - - describe 'Transforms', -> - it 'tokenizes transform functions', -> - tokens = grammar.tokenizeLines ''' - .transformed { - transform: matrix(0, 1.5, -1.5, 0, 0, 100px); - transform: rotate(90deg) translateX(100px) scale(1.5); - } - ''' - expect(tokens[1][1]).toEqual value: 'transform', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[1][4]).toEqual value: 'matrix', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] - expect(tokens[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[1][6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[1][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(tokens[1][12]).toEqual value: '-1.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[1][22]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[1][23]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[2][4]).toEqual value: 'rotate', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] - expect(tokens[2][10]).toEqual value: 'translateX', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] - expect(tokens[2][16]).toEqual value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] - - describe "performance regressions", -> - it "does not hang when tokenizing invalid input preceding an equals sign", -> - grammar = atom.grammars.grammarForScopeName('source.css') - start = Date.now() - grammar.tokenizeLine(' - start = Date.now() - grammar.tokenizeLines """ - - [}~#{'ÁÂÃÄÅÆÇÈÊËÍÎ'.repeat(100)} - - """ - expect(Date.now() - start).toBeLessThan(5000) - - describe "firstLineMatch", -> - it "recognises Emacs modelines", -> - valid = """ - #-*- CSS -*- - #-*- mode: CSS -*- - /* -*-css-*- */ - // -*- CSS -*- - /* -*- mode:CSS -*- */ - // -*- font:bar;mode:CSS -*- - // -*- font:bar;mode:CSS;foo:bar; -*- - // -*-font:mode;mode:CSS-*- - // -*- foo:bar mode: css bar:baz -*- - " -*-foo:bar;mode:css;bar:foo-*- "; - " -*-font-mode:foo;mode:css;foo-bar:quux-*-" - "-*-font:x;foo:bar; mode : CsS; bar:foo;foooooo:baaaaar;fo:ba;-*-"; - "-*- font:x;foo : bar ; mode : cSS ; bar : foo ; foooooo:baaaaar;fo:ba-*-"; - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - /* --*css-*- */ - /* -*-- CSS -*- - /* -*- -- CSS -*- - /* -*- CSS -;- -*- - // -*- CCSS -*- - // -*- CSS; -*- - // -*- css-stuff -*- - /* -*- model:css -*- - /* -*- indent-mode:css -*- - // -*- font:mode;CSS -*- - // -*- mode: -*- CSS - // -*- mode: I-miss-plain-old-css -*- - // -*-font:mode;mode:css--*- - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - it "recognises Vim modelines", -> - valid = """ - vim: se filetype=css: - # vim: se ft=css: - # vim: set ft=CSS: - # vim: set filetype=CSS: - # vim: ft=CSS - # vim: syntax=CSS - # vim: se syntax=css: - # ex: syntax=CSS - # vim:ft=css - # vim600: ft=css - # vim>600: set ft=css: - # vi:noai:sw=3 ts=6 ft=CSS - # vi::::::::::noai:::::::::::: ft=CSS - # vim:ts=4:sts=4:sw=4:noexpandtab:ft=cSS - # vi:: noai : : : : sw =3 ts =6 ft =Css - # vim: ts=4: pi sts=4: ft=CSS: noexpandtab: sw=4: - # vim: ts=4 sts=4: ft=css noexpandtab: - # vim:noexpandtab sts=4 ft=css ts=4 - # vim:noexpandtab:ft=css - # vim:ts=4:sts=4 ft=css:noexpandtab:\x20 - # vim:noexpandtab titlestring=hi\|there\\\\ ft=css ts=4 - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - ex: se filetype=css: - _vi: se filetype=CSS: - vi: se filetype=CSS - # vim set ft=css3 - # vim: soft=css - # vim: clean-syntax=css: - # vim set ft=css: - # vim: setft=CSS: - # vim: se ft=css backupdir=tmp - # vim: set ft=css set cmdheight=1 - # vim:noexpandtab sts:4 ft:CSS ts:4 - # vim:noexpandtab titlestring=hi\\|there\\ ft=CSS ts=4 - # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=CSS ts=4 - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - describe "Missing supported properties regressions", -> - it "recognises place-items property as supported", -> - tokens = grammar.tokenizeLines 'a { place-items: center center; }' - expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][4]).toEqual value: 'place-items', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "recognises place-self property as supported", -> - tokens = grammar.tokenizeLines 'a { place-self: center center; }' - expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][4]).toEqual value: 'place-self', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "recognises place-content property as supported", -> - tokens = grammar.tokenizeLines 'a { place-content: center center; }' - expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][4]).toEqual value: 'place-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "recognises row-gap property as supported", -> - tokens = grammar.tokenizeLines 'a { row-gap: 5px; }' - expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][4]).toEqual value: 'row-gap', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][7]).toEqual value: '5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[0][8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[0][9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[0][10]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][11]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] diff --git a/packages/language-css/spec/css-spec.js b/packages/language-css/spec/css-spec.js index c092ee0070..20f1373cf0 100644 --- a/packages/language-css/spec/css-spec.js +++ b/packages/language-css/spec/css-spec.js @@ -1,10 +1,4 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS205: Consider reworking code to avoid use of IIFEs - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe('CSS grammar', function() { let grammar = null; @@ -13,36 +7,36 @@ describe('CSS grammar', function() { waitsForPromise(() => atom.packages.activatePackage('language-css')); - return runs(() => grammar = atom.grammars.grammarForScopeName('source.css')); + runs(() => grammar = atom.grammars.grammarForScopeName('source.css')); }); it('parses the grammar', function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe('source.css'); + expect(grammar.scopeName).toBe('source.css'); }); describe('selectors', function() { it('tokenizes type selectors', function() { const {tokens} = grammar.tokenizeLine('p {}'); - return expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); }); it('tokenizes the universal selector', function() { const {tokens} = grammar.tokenizeLine('*'); - return expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); }); it('tokenises combinators', function() { const {tokens} = grammar.tokenizeLine('a > b + * ~ :not(.nah)'); expect(tokens[2]).toEqual({value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); expect(tokens[6]).toEqual({value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); - return expect(tokens[10]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(tokens[10]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); }); it('highlights deprecated combinators', function() { const {tokens} = grammar.tokenizeLine('.sooo /deep/ >>>_.>>>'); expect(tokens[3]).toEqual({value: '/deep/', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); - return expect(tokens[5]).toEqual({value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); + expect(tokens[5]).toEqual({value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); }); it('tokenizes complex selectors', function() { @@ -129,41 +123,41 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(lines[4][12]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[4][13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); expect(lines[4][15]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(lines[4][17]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][17]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); describe('custom elements (as type selectors)', function() { it('only tokenizes identifiers beginning with [a-z]', function() { const {tokens} = grammar.tokenizeLine('pearl-1941 1941-pearl -pearl-1941'); expect(tokens[0]).toEqual({value: 'pearl-1941', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); - return expect(tokens[1]).toEqual({value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[1]).toEqual({value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css']}); }); it('tokenizes custom elements containing non-ASCII letters', function() { const {tokens} = grammar.tokenizeLine('pokémon-ピカチュウ'); - return expect(tokens[0]).toEqual({value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[0]).toEqual({value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); }); it('does not tokenize identifiers containing [A-Z]', function() { const {tokens} = grammar.tokenizeLine('Basecamp-schedule basecamp-Schedule'); - return expect(tokens[0]).toEqual({value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[0]).toEqual({value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css']}); }); it('does not tokenize identifiers containing no hyphens', function() { const {tokens} = grammar.tokenizeLine('halo_night'); - return expect(tokens[0]).toEqual({value: 'halo_night', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[0]).toEqual({value: 'halo_night', scopes: ['source.css', 'meta.selector.css']}); }); it('does not tokenise identifiers following an @ symbol', function() { const {tokens} = grammar.tokenizeLine('@some-weird-new-feature'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); - return expect(tokens[1]).toEqual({value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + expect(tokens[1]).toEqual({value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); }); - return it('does not tokenise identifiers in unfamiliar functions', function() { + it('does not tokenise identifiers in unfamiliar functions', function() { const {tokens} = grammar.tokenizeLine('some-edgy-new-function()'); expect(tokens[0]).toEqual({value: 'some-edgy-new-function(', scopes: ['source.css', 'meta.selector.css']}); - return expect(tokens[1]).toEqual({value: ')', scopes: ['source.css']}); + expect(tokens[1]).toEqual({value: ')', scopes: ['source.css']}); }); }); @@ -172,7 +166,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], const {tokens} = grammar.tokenizeLine('[title]'); expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[1]).toEqual({value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - return expect(tokens[2]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[2]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes attribute selectors with identifier values', function() { @@ -181,7 +175,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[1]).toEqual({value: 'hreflang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[2]).toEqual({value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); expect(tokens[3]).toEqual({value: 'fr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); - return expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes attribute selectors with string values', function() { @@ -192,7 +186,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'http://www.w3.org/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names with wildcard prefix', function() { @@ -201,7 +195,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[1]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); expect(tokens[2]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); expect(tokens[3]).toEqual({value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - return expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names with namespace prefix', function() { @@ -212,7 +206,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: 'origin', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[4]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); expect(tokens[5]).toEqual({value: 'radiation', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); - return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names without namespace prefix', function() { @@ -224,7 +218,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[5]).toEqual({value: '75', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises compound ID/attribute selectors', function() { @@ -241,7 +235,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[2]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); expect(tokens[3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[4]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); - return expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); }); it('tokenises compound class/attribute selectors', function() { @@ -259,7 +253,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(tokens[4]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('allows whitespace to be inserted between tokens', function() { @@ -276,7 +270,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[10]).toEqual({value: '%%', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[11]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[12]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - return expect(tokens[13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences inside attribute selectors', function() { @@ -286,7 +280,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: '0', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[5]).toEqual({value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); expect(tokens[6]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); - return expect(tokens[10]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[10]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences inside namespace prefixes', function() { @@ -300,7 +294,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[8]).toEqual({value: 'It', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[9]).toEqual({value: '\\?', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); expect(tokens[10]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); - return expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises comments inside attribute selectors', function() { @@ -311,7 +305,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[5]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises quoted strings in attribute selectors', function() { @@ -343,7 +337,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[24]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css']}); expect(tokens[25]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); expect(tokens[26]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - return expect(tokens[27]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[27]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises unquoted strings in attribute selectors', function() { @@ -357,7 +351,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); expect(tokens[5]).toEqual({value: '0xDEADCAFE=|~BEEFBABE', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - return expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences in unquoted strings', function() { @@ -371,7 +365,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[12]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css']}); expect(tokens[13]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); - return expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises the ignore-case modifier at the end of a selector', function() { @@ -398,10 +392,10 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[54]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[55]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); expect(tokens[56]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); - return expect(tokens[57]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[57]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); - return it('tokenises attribute selectors spanning multiple lines', function() { + it('tokenises attribute selectors spanning multiple lines', function() { let lines = grammar.tokenizeLines(`\ span[ \\x20{2} @@ -455,7 +449,7 @@ i]\ expect(lines[3][0]).toEqual({value: ' |', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); expect(lines[4][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[5][0]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); - return expect(lines[5][1]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(lines[5][1]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); }); @@ -467,19 +461,19 @@ i]\ ({tokens} = grammar.tokenizeLine('.スポンサー')); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[1]).toEqual({value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes a class selector consisting of two hypens', function() { const {tokens} = grammar.tokenizeLine('.--'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[1]).toEqual({value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes class selectors consisting of one (valid) character', function() { const {tokens} = grammar.tokenizeLine('._'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[1]).toEqual({value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenises class selectors starting with an escape sequence', function() { @@ -488,7 +482,7 @@ i]\ expect(tokens[1]).toEqual({value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css']}); expect(tokens[2]).toEqual({value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css']}); expect(tokens[3]).toEqual({value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); - return expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises class selectors ending with an escape sequence', function() { @@ -498,35 +492,35 @@ i]\ expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css']}); expect(tokens[3]).toEqual({value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(tokens[4]).toEqual({value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css']}); - return expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it contains unescaped ASCII punctuation or symbols other than "-" and "_"', function() { const {tokens} = grammar.tokenizeLine('.B&W{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'B&W', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it starts with ASCII digits ([0-9])', function() { const {tokens} = grammar.tokenizeLine('.666{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it starts with "-" followed by ASCII digits', function() { const {tokens} = grammar.tokenizeLine('.-911-{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); - return it('marks a class invalid if it consists of only one hyphen', function() { + it('marks a class invalid if it consists of only one hyphen', function() { const {tokens} = grammar.tokenizeLine('.-{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); }); @@ -534,53 +528,53 @@ i]\ it('tokenizes id selectors consisting of ASCII letters', function() { const {tokens} = grammar.tokenizeLine('#unicorn'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[1]).toEqual({value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors containing non-ASCII letters', function() { const {tokens} = grammar.tokenizeLine('#洪荒之力'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[1]).toEqual({value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors containing [0-9], "-", or "_"', function() { const {tokens} = grammar.tokenizeLine('#_zer0-day'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[1]).toEqual({value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors beginning with two hyphens', function() { const {tokens} = grammar.tokenizeLine('#--d3bug--'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[1]).toEqual({value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('marks an id invalid if it contains ASCII punctuation or symbols other than "-" and "_"', function() { const {tokens} = grammar.tokenizeLine('#sort!{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'sort!', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it starts with ASCII digits ([0-9])', function() { const {tokens} = grammar.tokenizeLine('#666{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it starts with "-" followed by ASCII digits', function() { const {tokens} = grammar.tokenizeLine('#-911-{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it consists of one hyphen only', function() { const {tokens} = grammar.tokenizeLine('#-{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises ID selectors starting with an escape sequence', function() { @@ -589,17 +583,17 @@ i]\ expect(tokens[1]).toEqual({value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css']}); expect(tokens[2]).toEqual({value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css']}); expect(tokens[3]).toEqual({value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); - return expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); - return it('tokenises ID selectors ending with an escape sequence', function() { + it('tokenises ID selectors ending with an escape sequence', function() { const {tokens} = grammar.tokenizeLine('#la\\{tex\\} {'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css']}); expect(tokens[3]).toEqual({value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[4]).toEqual({value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css']}); - return expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); }); @@ -611,7 +605,7 @@ i]\ expect(tokens[2]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[3]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises anonymous namespace prefixes', function() { @@ -643,7 +637,7 @@ i]\ expect(tokens[1]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[2]).toEqual({value: 'svg', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); expect(tokens[3]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); - return expect(tokens[4]).toEqual({value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[4]).toEqual({value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); }); it('tokenises the "no-namespace" prefix', function() { @@ -651,10 +645,10 @@ i]\ expect(tokens[0]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); expect(tokens[1]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[3]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it("doesn't tokenise prefixes without a selector", function() { + it("doesn't tokenise prefixes without a selector", function() { let {tokens} = grammar.tokenizeLine('*| { }'); expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css']}); @@ -666,7 +660,7 @@ i]\ expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -688,10 +682,10 @@ i]\ expect(lines[0][1]).toEqual({value: ' Not the first line ', scopes: ['source.css', 'comment.block.css']}); expect(lines[0][2]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[1][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); - return expect(lines[1][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + expect(lines[1][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); }); - return it('highlights invalid @charset statements', function() { + it('highlights invalid @charset statements', function() { let lines = grammar.tokenizeLines(" @charset 'US-ASCII';"); expect(lines[0][0]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.leading-whitespace.charset.css']}); expect(lines[0][1]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); @@ -741,7 +735,7 @@ i]\ lines = grammar.tokenizeLines("@CHARSET 'US-ASCII';"); expect(lines[0][0]).toEqual({value: '@CHARSET', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-lowercase.charset.css']}); expect(lines[0][1]).toEqual({value: " 'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css']}); - return expect(lines[0][2]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + expect(lines[0][2]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); }); }); @@ -769,7 +763,7 @@ i]\ ({tokens} = grammar.tokenizeLine("@import 'file.css';")); expect(tokens[3]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css']}); - return expect(tokens[5]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[5]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); }); it("doesn't let injected comments impact parameter matching", function() { @@ -793,7 +787,7 @@ i]\ expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[6]).toEqual({value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('correctly handles word boundaries', function() { @@ -809,7 +803,7 @@ i]\ expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'import-file', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); expect(tokens[2]).toEqual({value: '.css', scopes: ['source.css', 'meta.at-rule.header.css']}); - return expect(tokens[3]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css']}); + expect(tokens[3]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css']}); }); it('matches a URL that starts on the next line', function() { @@ -823,7 +817,7 @@ i]\ expect(lines[1][3]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(lines[1][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[1][5]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('matches comments inside query lists', function() { @@ -841,7 +835,7 @@ i]\ expect(tokens[13]).toEqual({value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[16]).toEqual({value: 'all', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css']}); - return expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('highlights deprecated media types', function() { @@ -852,10 +846,10 @@ i]\ expect(tokens[4]).toEqual({value: 'astral.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[7]).toEqual({value: 'projection', scopes: ['source.css', 'meta.at-rule.import.css', 'invalid.deprecated.constant.media.css']}); - return expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); - return it('highlights media features in query lists', function() { + it('highlights media features in query lists', function() { const {tokens} = grammar.tokenizeLine('@import url(\'landscape.css\') screen and (orientation:landscape);'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); @@ -872,7 +866,7 @@ i]\ expect(tokens[16]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.separator.key-value.css']}); expect(tokens[17]).toEqual({value: 'landscape', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.property-value.css']}); expect(tokens[18]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.end.bracket.round.css']}); - return expect(tokens[19]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[19]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); }); @@ -904,7 +898,7 @@ i]\ expect(tokens[14]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights deprecated media types', function() { @@ -918,7 +912,7 @@ i]\ expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[10]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights vendored media features', function() { @@ -968,7 +962,7 @@ i]\ expect(tokens[4]).toEqual({value: 'mso-page-size', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: 'wide', scopes: ['source.css', 'meta.at-rule.media.header.css']}); - return expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); }); it('tokenises @media immediately following a closing brace', function() { @@ -998,7 +992,7 @@ i]\ expect(tokens[14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); expect(tokens[15]).toEqual({value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[17]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises level 4 media-query syntax', function() { @@ -1012,7 +1006,7 @@ i]\ expect(lines[0][6]).toEqual({value: '>=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); expect(lines[1][6]).toEqual({value: '<=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); expect(lines[2][6]).toEqual({value: '>', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); - return expect(lines[3][6]).toEqual({value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); + expect(lines[3][6]).toEqual({value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); }); it('tokenises comments between media types', function() { @@ -1035,10 +1029,10 @@ i]\ expect(tokens[19]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[20]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[21]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); - return it('tokenises comments between media features', function() { + it('tokenises comments between media features', function() { const {tokens} = grammar.tokenizeLine('@media/*=*/(max-width:/**/37.5em)/*=*/and/*=*/(/*=*/min-height/*:*/:/*=*/1.2em/*;*/){}'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); @@ -1079,7 +1073,7 @@ i]\ expect(tokens[36]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[37]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[38]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[39]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[39]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); }); @@ -1147,7 +1141,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[3][23]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); expect(lines[3][24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(lines[3][26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(lines[3][28]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(lines[3][28]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights invalid commas', function() { @@ -1164,7 +1158,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[3]).toEqual({value: ', ,', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css']}); expect(tokens[4]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('allows spaces inside ratio values', function() { @@ -1178,7 +1172,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[21]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); expect(tokens[22]).toEqual({value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css']}); expect(tokens[23]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); - return expect(tokens[24]).toEqual({value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); + expect(tokens[24]).toEqual({value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); }); describe('@keyframes', function() { @@ -1229,7 +1223,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[4][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(lines[4][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[4][12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1250,7 +1244,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][0]).toEqual({value: ' { Nah { margin-top: 2em; }', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css']}); expect(lines[2][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[2][1]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css']}); - return expect(lines[2][3]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + expect(lines[2][3]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); }); it('matches offset keywords case-insensitively', function() { @@ -1266,22 +1260,22 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[13]).toEqual({value: 'To', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); expect(tokens[15]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); expect(tokens[16]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); }); it('matches percentile offsets', function() { const {tokens} = grammar.tokenizeLine('@keyframes identifier { -50.2% } @keyframes ident2 { .25%}'); expect(tokens[7]).toEqual({value: '-50.2%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); - return expect(tokens[18]).toEqual({value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); + expect(tokens[18]).toEqual({value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); }); - return it('highlights escape sequences inside identifiers', function() { + it('highlights escape sequences inside identifiers', function() { const {tokens} = grammar.tokenizeLine('@keyframes A\\1F602Z'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css']}); expect(tokens[3]).toEqual({value: 'A', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); expect(tokens[4]).toEqual({value: '\\1F602', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css', 'constant.character.escape.codepoint.css']}); - return expect(tokens[5]).toEqual({value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + expect(tokens[5]).toEqual({value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); }); }); @@ -1299,7 +1293,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); expect(tokens[10]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[11]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); - return expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('matches logical operators', function() { @@ -1311,7 +1305,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati ); expect(lines[0][3]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css']}); expect(lines[1][11]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css']}); - return expect(lines[2][11]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); + expect(lines[2][11]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); }); it('matches custom variables in feature queries', function() { @@ -1320,7 +1314,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[4]).toEqual({value: '--foo', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'variable.css']}); expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); expect(tokens[7]).toEqual({value: 'green', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); - return expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); }); it("doesn't mistake brackets in string literals for feature queries", function() { @@ -1348,7 +1342,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][10]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[1][11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[1][13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('tokenises multiple feature queries', function() { @@ -1374,7 +1368,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[23]).toEqual({value: 'run-in', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); expect(tokens[25]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); - return expect(tokens[26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + expect(tokens[26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); }); it('embeds rulesets and other at-rules', function() { @@ -1475,7 +1469,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[13][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[13][12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); expect(lines[14][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); - return expect(lines[15][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(lines[15][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1510,10 +1504,10 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][20]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css']}); expect(lines[1][21]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[1][22]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); - return expect(lines[1][23]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(lines[1][23]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); - return it('matches feature queries across multiple lines', function() { + it('matches feature queries across multiple lines', function() { const lines = grammar.tokenizeLines(`\ @supports (box-shadow: 0 0 2px rgba(0,0,0,.5) inset) or @@ -1582,7 +1576,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[5][3]).toEqual({value: 'noticebox', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(lines[5][5]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); expect(lines[5][7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); }); @@ -1619,7 +1613,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[6]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it("doesn't confuse a prefix of 'url' as a function", function() { @@ -1633,7 +1627,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[8]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(tokens[9]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(tokens[11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('permits injected comments between tokens', function() { @@ -1653,7 +1647,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[13]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('allows no spaces between "@namespace" and quoted URLs', function() { @@ -1663,7 +1657,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[2]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[3]).toEqual({value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css']}); expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('tokenises escape sequences in prefixes', function() { @@ -1671,10 +1665,10 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[3]).toEqual({value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); expect(tokens[4]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css', 'constant.character.escape.css']}); expect(tokens[5]).toEqual({value: 'fix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); - return expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); }); - return it('allows arguments to span multiple lines', function() { + it('allows arguments to span multiple lines', function() { let lines = grammar.tokenizeLines(`\ @namespace prefix"XML";\ @@ -1705,7 +1699,7 @@ url("http://a.bc/");\ expect(lines[4][3]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(lines[4][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[4][5]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(lines[4][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(lines[4][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); }); @@ -1718,7 +1712,7 @@ url("http://a.bc/");\ expect(tokens[3]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('allows font-feature names to start on a different line', function() { @@ -1731,7 +1725,7 @@ Font name 2 expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css']}); expect(lines[0][1]).toEqual({value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css']}); expect(lines[1][0]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); - return expect(lines[2][0]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[2][0]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1750,7 +1744,7 @@ Font name 2 expect(tokens[11]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css']}); expect(tokens[12]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[13]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); - return expect(tokens[14]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[14]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises at-rules for feature names', function() { @@ -1811,7 +1805,7 @@ Font name 2 expect(lines[5][4]).toEqual({value: 'charvar', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); expect(lines[5][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); expect(lines[5][7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); - return expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('matches feature-name rules case-insensitively', function() { @@ -1829,7 +1823,7 @@ Font name 2 expect(lines[2][1]).toEqual({value: 'anNOTatION', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css']}); expect(lines[3][1]).toEqual({value: 'styLISTic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css']}); expect(lines[4][1]).toEqual({value: 'STYLEset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css']}); - return expect(lines[5][1]).toEqual({value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css']}); + expect(lines[5][1]).toEqual({value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css']}); }); it('matches comments inside feature-name rules', function() { @@ -1859,10 +1853,10 @@ Font name 2 expect(lines[2][8]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[2][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[2][10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it('highlights escape sequences inside feature-names', function() { + it('highlights escape sequences inside feature-names', function() { const {tokens} = grammar.tokenizeLine('@swash{ s\\000077a\\73hy: 1; }'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css']}); @@ -1870,7 +1864,7 @@ Font name 2 expect(tokens[5]).toEqual({value: '\\000077', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css']}); expect(tokens[6]).toEqual({value: 'a', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); expect(tokens[7]).toEqual({value: '\\73', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css']}); - return expect(tokens[8]).toEqual({value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(tokens[8]).toEqual({value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); }); }); @@ -1897,7 +1891,7 @@ Font name 2 expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[3]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); })); describe('@counter-style', function() { @@ -1938,7 +1932,7 @@ Font name 2 expect(lines[3][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(lines[3][6]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[3][7]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); - return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1957,7 +1951,7 @@ Font name 2 expect(tokens[12]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css']}); expect(tokens[14]).toEqual({value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[17]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[17]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("allows the counter-style's name to start on a different line", function() { @@ -1968,16 +1962,16 @@ winners-list\ ); expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); expect(lines[0][1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); - return expect(lines[1][0]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + expect(lines[1][0]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); }); - return it("highlights escape sequences inside the style's name", function() { + it("highlights escape sequences inside the style's name", function() { const {tokens} = grammar.tokenizeLine('@counter-style A\\01F602z'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); expect(tokens[3]).toEqual({value: 'A', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); expect(tokens[4]).toEqual({value: '\\01F602', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css', 'constant.character.escape.codepoint.css']}); - return expect(tokens[5]).toEqual({value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + expect(tokens[5]).toEqual({value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); }); }); @@ -2028,7 +2022,7 @@ regexp("https:.*") { expect(lines[4][8]).toEqual({value: 'f00', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css']}); expect(lines[4][9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[4][11]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[5][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css']}); + expect(lines[5][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css']}); })); describe('@viewport', function() { @@ -2048,7 +2042,7 @@ regexp("https:.*") { expect(tokens[15]).toEqual({value: '800', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(tokens[16]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises them across lines', function() { @@ -2076,10 +2070,10 @@ regexp("https:.*") { expect(lines[4][2]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[4][4]).toEqual({value: '0.9', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[4][5]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it('tokenises injected comments', function() { + it('tokenises injected comments', function() { const lines = grammar.tokenizeLines(`\ @-ms-viewport/*{*/{/* ==*/orientation: landscape; @@ -2099,11 +2093,11 @@ regexp("https:.*") { expect(lines[1][3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[1][5]).toEqual({value: 'landscape', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); - return describe('unknown at-rules', function() { + describe('unknown at-rules', function() { it('correctly parses single-line unknown at-rules closing with semicolons', function() { const lines = grammar.tokenizeLines(`\ @foo; @@ -2124,10 +2118,10 @@ regexp("https:.*") { expect(lines[3][2]).toEqual({value: ' ()', scopes: ['source.css', 'meta.at-rule.header.css']}); expect(lines[4][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); - return expect(lines[4][2]).toEqual({value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css']}); + expect(lines[4][2]).toEqual({value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css']}); }); - return it('correctly parses single-line unknown at-rules closing with ;', function() { + it('correctly parses single-line unknown at-rules closing with ;', function() { const lines = grammar.tokenizeLines(`\ @foo bar; .foo\ @@ -2136,7 +2130,7 @@ regexp("https:.*") { expect(lines[0][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); expect(lines[1][0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(lines[1][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(lines[1][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); }); }); @@ -2157,7 +2151,7 @@ regexp("https:.*") { expect(lines[2][1]).toEqual({value: 'pAgE', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); expect(lines[2][4]).toEqual({value: 'fIRST', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(lines[3][1]).toEqual({value: 'NAMEspace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); - return expect(lines[4][1]).toEqual({value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css']}); + expect(lines[4][1]).toEqual({value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css']}); }); it('ignores case in property names', function() { @@ -2171,7 +2165,7 @@ a{ -MOZ-IMAGE: none; }\ expect(lines[0][3]).toEqual({value: 'COLOR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(lines[1][3]).toEqual({value: 'gRId-tEMPLaTe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(lines[2][3]).toEqual({value: 'bACkgrOUND-iMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); - return expect(lines[3][3]).toEqual({value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); + expect(lines[3][3]).toEqual({value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); }); it('ignores case in property keywords', function() { @@ -2193,7 +2187,7 @@ a{ font: HelVETica; }\ expect(lines[4][6]).toEqual({value: 'NONe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(lines[5][6]).toEqual({value: 'lOWER-lATIN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); expect(lines[6][6]).toEqual({value: '-WebkIT-foo', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); - return expect(lines[7][6]).toEqual({value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + expect(lines[7][6]).toEqual({value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); }); it('ignores case in selectors', function() { @@ -2218,7 +2212,7 @@ I::-mOZ-thing {}\ expect(lines[4][2]).toEqual({value: 'NOT', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(lines[5][0]).toEqual({value: 'I', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(lines[5][2]).toEqual({value: 'BACKDROP', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); - return expect(lines[6][2]).toEqual({value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(lines[6][2]).toEqual({value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); it('ignores case in function names', function() { @@ -2240,10 +2234,10 @@ a{ content: cALc(2 + 2)}\ expect(lines[4][6]).toEqual({value: 'CoUNTer', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(lines[5][6]).toEqual({value: 'cuBIC-beZIER', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); expect(lines[6][6]).toEqual({value: 'sTePs', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); - return expect(lines[7][6]).toEqual({value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); + expect(lines[7][6]).toEqual({value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); }); - return it('ignores case in unit names', function() { + it('ignores case in unit names', function() { const lines = grammar.tokenizeLines(`\ a{width: 20EM; } a{width: 20ReM; } @@ -2261,7 +2255,7 @@ a{width: 2gRAd}\ expect(lines[3][6]).toEqual({value: 'S', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.s.css']}); expect(lines[4][5]).toEqual({value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[4][6]).toEqual({value: 'CM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css']}); - return expect(lines[5][6]).toEqual({value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css']}); + expect(lines[5][6]).toEqual({value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css']}); }); }); @@ -2270,7 +2264,7 @@ a{width: 2gRAd}\ const {tokens} = grammar.tokenizeLine('p:first-child'); expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[2]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); }); it("doesn't tokenise pseudo-classes if followed by a semicolon or closed bracket", function() { @@ -2280,7 +2274,7 @@ a{width: 2gRAd}\ expect(tokens[3]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[5]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); - return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); describe(':dir()', function() { @@ -2303,10 +2297,10 @@ a:dir(ltr ){ } expect(lines[1][3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[1][4]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); expect(lines[1][5]).toEqual({value: 'rtl', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); - return expect(lines[1][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[1][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('allows :dir() to include comments and newlines', function() { + it('allows :dir() to include comments and newlines', function() { const lines = grammar.tokenizeLines(`\ :DIR(/** ==*/ltr/* @@ -2323,7 +2317,7 @@ a:dir(ltr ){ } expect(lines[1][2]).toEqual({value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); expect(lines[1][3]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[2][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(lines[2][1]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][1]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2336,15 +2330,15 @@ a:dir(ltr ){ } expect(tokens[3]).toEqual({value: 'zh-Hans-CN', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css']}); expect(tokens[4]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); expect(tokens[5]).toEqual({value: 'es-419', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css']}); - return expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('does not tokenize unquoted language ranges containing asterisks', function() { const {tokens} = grammar.tokenizeLine(':lang(zh-*-CN)'); - return expect(tokens[3]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[3]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css']}); }); - return it('tokenizes language ranges containing asterisks quoted as strings', function() { + it('tokenizes language ranges containing asterisks quoted as strings', function() { const {tokens} = grammar.tokenizeLine(':lang("zh-*-CN",\'*-ab-\')'); expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'support.constant.language-range.css']}); @@ -2352,7 +2346,7 @@ a:dir(ltr ){ } expect(tokens[6]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); expect(tokens[7]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[8]).toEqual({value: '*-ab-', scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'support.constant.language-range.css']}); - return expect(tokens[9]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[9]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); }); }); @@ -2369,10 +2363,10 @@ a:dir(ltr ){ } expect(tokens[8]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[10]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); - return expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('tokenises injected comments', function() { + it('tokenises injected comments', function() { const {tokens} = grammar.tokenizeLine('*:not(/*(*/.class-name/*)*/):not(/*b*/) {}'); expect(tokens[2]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2391,11 +2385,11 @@ a:dir(ltr ){ } expect(tokens[16]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[17]).toEqual({value: 'b', scopes: ['source.css', 'meta.selector.css', 'comment.block.css']}); expect(tokens[18]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); - return describe(':nth-*()', function() { + describe(':nth-*()', function() { it('tokenizes :nth-child()', function() { const tokens = grammar.tokenizeLines(`\ :nth-child(2n+1) @@ -2421,7 +2415,7 @@ a:dir(ltr ){ } expect(tokens[6][3]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[6][4]).toEqual({value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); expect(tokens[7][4]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); - return expect(tokens[7][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[7][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); }); it('tokenizes :nth-last-child()', function() { @@ -2440,7 +2434,7 @@ a:dir(ltr ){ } expect(tokens[1][4]).toEqual({value: '-2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[2][4]).toEqual({value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[2][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[3][3]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); + expect(tokens[3][3]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); }); it('tokenizes :nth-of-type()', function() { @@ -2456,10 +2450,10 @@ img:nth-of-type(n+1)\ expect(tokens[0][4]).toEqual({value: '+n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[0][5]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[1][4]).toEqual({value: '-n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); - return expect(tokens[2][4]).toEqual({value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[2][4]).toEqual({value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); }); - return it('tokenizes ::nth-last-of-type()', function() { + it('tokenizes ::nth-last-of-type()', function() { const tokens = grammar.tokenizeLines(`\ h1:nth-last-of-type(-1) h1:nth-last-of-type(+2) @@ -2472,7 +2466,7 @@ h1:nth-last-of-type(3)\ expect(tokens[0][4]).toEqual({value: '-1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[0][5]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[1][4]).toEqual({value: '+2', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); - return expect(tokens[2][4]).toEqual({value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[2][4]).toEqual({value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); }); }); }); @@ -2489,7 +2483,7 @@ h1:nth-last-of-type(3)\ ({tokens} = grammar.tokenizeLine('q::after')); expect(tokens[0]).toEqual({value: 'q', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(tokens[2]).toEqual({value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); it('tokenizes both : and :: notations for vendor-prefixed pseudo-elements', function() { @@ -2499,39 +2493,39 @@ h1:nth-last-of-type(3)\ ({tokens} = grammar.tokenizeLine('::-webkit-input-placeholder')); expect(tokens[0]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(tokens[1]).toEqual({value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); - return it('only tokenizes the :: notation for other pseudo-elements', function() { + it('only tokenizes the :: notation for other pseudo-elements', function() { let {tokens} = grammar.tokenizeLine('::selection'); expect(tokens[0]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); ({tokens} = grammar.tokenizeLine(':selection')); - return expect(tokens[0]).toEqual({value: ':selection', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[0]).toEqual({value: ':selection', scopes: ['source.css', 'meta.selector.css']}); }); }); - return describe('compound selectors', function() { + describe('compound selectors', function() { it('tokenizes the combination of type selectors followed by class selectors', function() { const {tokens} = grammar.tokenizeLine('very-custom.class'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[2]).toEqual({value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes the combination of type selectors followed by pseudo-classes', function() { const {tokens} = grammar.tokenizeLine('very-custom:hover'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[2]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); }); - return it('tokenizes the combination of type selectors followed by pseudo-elements', function() { + it('tokenizes the combination of type selectors followed by pseudo-elements', function() { const {tokens} = grammar.tokenizeLine('very-custom::shadow'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(tokens[2]).toEqual({value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); }); }); @@ -2544,7 +2538,7 @@ h1:nth-last-of-type(3)\ expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes compact inline property lists', function() { @@ -2556,7 +2550,7 @@ h1:nth-last-of-type(3)\ expect(tokens[6]).toEqual({value: 'float', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(tokens[7]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[8]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); - return expect(tokens[9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes multiple inline property lists', function() { @@ -2578,17 +2572,17 @@ another-one { display : none ; }\ expect(tokens[1][8]).toEqual({value: 'none', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[1][9]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[1][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[1][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[1][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes custom properties', function() { const {tokens} = grammar.tokenizeLine(':root { --white: #FFF; }'); - return expect(tokens[5]).toEqual({value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css']}); + expect(tokens[5]).toEqual({value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css']}); }); it('tokenises commas between property values', function() { const {tokens} = grammar.tokenizeLine('a{ text-shadow: a, b; }'); - return expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); }); it('tokenises superfluous semicolons', function() { @@ -2601,13 +2595,13 @@ another-one { display : none ; }\ expect(lines[0][i+9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[1][i]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); } - return expect(lines[1][9]).toEqual({value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][9]).toEqual({value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); }); - return describe('values', function() { + describe('values', function() { it('tokenizes color keywords', function() { const {tokens} = grammar.tokenizeLine('#jon { color: snow; }'); - return expect(tokens[8]).toEqual({value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css']}); + expect(tokens[8]).toEqual({value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css']}); }); it('tokenises RGBA values in hex notation', function() { @@ -2628,25 +2622,25 @@ another-one { display : none ; }\ expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); ({tokens} = grammar.tokenizeLine('a{ color: #CAFEBABEF; }')); - return expect(tokens[6]).toEqual({value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[6]).toEqual({value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); }); it('tokenizes common font names', function() { const {tokens} = grammar.tokenizeLine('p { font-family: Verdana, Helvetica, sans-serif; }'); expect(tokens[7]).toEqual({value: 'Verdana', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); expect(tokens[10]).toEqual({value: 'Helvetica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); - return expect(tokens[13]).toEqual({value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + expect(tokens[13]).toEqual({value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); }); it('tokenizes predefined list style types', function() { const {tokens} = grammar.tokenizeLine('ol.myth { list-style-type: cjk-earthly-branch }'); - return expect(tokens[9]).toEqual({value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); + expect(tokens[9]).toEqual({value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); }); it('tokenizes numeric values', function() { const {tokens} = grammar.tokenizeLine('div { font-size: 14px; }'); expect(tokens[7]).toEqual({value: '14', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); - return expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); }); it('does not tokenize invalid numeric values', function() { @@ -2654,7 +2648,7 @@ another-one { display : none ; }\ expect(tokens[7]).toEqual({value: 'test14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); ({tokens} = grammar.tokenizeLine('div { font-size: test-14px; }')); - return expect(tokens[7]).toEqual({value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[7]).toEqual({value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); }); it('tokenizes vendor-prefixed values', function() { @@ -2665,12 +2659,12 @@ another-one { display : none ; }\ expect(tokens[8]).toEqual({value: '-moz-min-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); ({tokens} = grammar.tokenizeLine('.edge { display: -ms-grid; }')); - return expect(tokens[8]).toEqual({value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); + expect(tokens[8]).toEqual({value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); }); it('tokenizes custom variables', function() { const {tokens} = grammar.tokenizeLine('div { color: var(--primary-color) }'); - return expect(tokens[9]).toEqual({value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(tokens[9]).toEqual({value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); }); it('tokenises numeric values correctly', function() { @@ -2715,7 +2709,7 @@ another-one { display : none ; }\ expect(lines[11][8]).toEqual({value: '+.5E-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[11][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); expect(lines[12][8]).toEqual({value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); - return expect(lines[12][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(lines[12][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); }); describe('functional notation', function() { @@ -2729,10 +2723,10 @@ another-one { display : none ; }\ expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css']}); expect(tokens[11]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.constant.property-value.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it('matches variables', function() { + it('matches variables', function() { const {tokens} = grammar.tokenizeLine('a{content:ATTR(VAR(--name) px, "N/A")}'); expect(tokens[4]).toEqual({value: 'ATTR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2745,7 +2739,7 @@ another-one { display : none ; }\ expect(tokens[14]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[15]).toEqual({value: 'N/A', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css']}); expect(tokens[16]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2775,7 +2769,7 @@ a{ expect(lines[3][9]).toEqual({value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); expect(lines[4][7]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(lines[4][9]).toEqual({value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); - return expect(lines[4][11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(lines[4][11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); }); it('requires whitespace around + and - operators', function() { @@ -2789,7 +2783,7 @@ a{ expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[10]).toEqual({value: '--1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); expect(tokens[19]).toEqual({value: '10', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); - return expect(tokens[20]).toEqual({value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); + expect(tokens[20]).toEqual({value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); }); it('does not require whitespace around * and / operators', function() { @@ -2801,10 +2795,10 @@ a{ ({tokens} = grammar.tokenizeLine('a{ width: calc(3px/2); }')); expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[10]).toEqual({value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); - return expect(tokens[11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(tokens[11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); }); - return it('matches variable expansions inside calculations', function() { + it('matches variable expansions inside calculations', function() { const {tokens} = grammar.tokenizeLine('.foo { margin-top: calc(var(--gap) + 1px); }'); expect(tokens[8]).toEqual({value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2817,7 +2811,7 @@ a{ expect(tokens[18]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[20]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -2872,7 +2866,7 @@ a{ expect(tokens[12]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); expect(tokens[13]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); expect(tokens[14]).toEqual({value: '.7', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); - return expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('matches variables as colour components', function() { @@ -2882,7 +2876,7 @@ a{ expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[10]).toEqual({value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css']}); expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); }); it('matches comments between colour components', function() { @@ -2901,10 +2895,10 @@ a{ expect(tokens[21]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[22]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); expect(tokens[23]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[24]).toEqual({value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[24]).toEqual({value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); }); - return it('allows colour components to be split across lines', function() { + it('allows colour components to be split across lines', function() { const lines = grammar.tokenizeLines(`\ .frost{ background-color: rgba( @@ -2946,7 +2940,7 @@ a{ expect(lines[6][7]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[6][8]).toEqual({value: ' Transparency ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); expect(lines[6][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(lines[7][1]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[7][1]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2973,7 +2967,7 @@ a{ expect(tokens[16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); expect(tokens[18]).toEqual({value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); expect(tokens[19]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); - return expect(tokens[21]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(tokens[21]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); }); it('tokenises radial gradients', function() { @@ -3011,7 +3005,7 @@ a{ expect(tokens[36]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); expect(tokens[41]).toEqual({value: '.3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); expect(tokens[42]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[48]).toEqual({value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(tokens[48]).toEqual({value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); }); it('matches gradients that span multiple lines with injected comments', function() { @@ -3046,7 +3040,7 @@ a{ expect(lines[3][27]).toEqual({value: '))))))))}', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); expect(lines[3][28]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[3][29]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); - return expect(lines[3][30]).toEqual({value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); + expect(lines[3][30]).toEqual({value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); }); it('highlights vendored gradient functions', function() { @@ -3082,10 +3076,10 @@ a{ expect(lines[3][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[3][10]).toEqual({value: ' For old Opera (11.1 to 12.0) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); expect(lines[3][13]).toEqual({value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); - return expect(lines[3][14]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[3][14]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); }); - return it('highlights antique Webkit syntax as deprecated', function() { + it('highlights antique Webkit syntax as deprecated', function() { const lines = grammar.tokenizeLines(`\ .grad { background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, @@ -3155,7 +3149,7 @@ a{ expect(lines[9][8]).toEqual({value: '150', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); expect(lines[9][54]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); expect(lines[9][55]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[10][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[10][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3194,7 +3188,7 @@ a{ expect(lines[2][16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css']}); expect(lines[2][18]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); expect(lines[2][19]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); - return expect(lines[2][20]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][20]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('tokenises OpenType feature functions', function() { @@ -3241,10 +3235,10 @@ a{ expect(lines[7][9]).toEqual({value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(lines[7][10]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[7][11]).toEqual({value: 'ident2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); - return expect(lines[7][12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[7][12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('tokenises image-set()', function() { + it('tokenises image-set()', function() { const lines = grammar.tokenizeLines(`\ a{ background-image: image-set( "foo.png" 1x, @@ -3276,7 +3270,7 @@ a{ expect(lines[3][6]).toEqual({value: 'dpi', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css', 'keyword.other.unit.dpi.css']}); expect(lines[3][8]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); expect(lines[3][9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3299,10 +3293,10 @@ a{ expect(tokens[19]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css']}); expect(tokens[20]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[21]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[22]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[22]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('highlights the "start" and "end" keywords', function() { + it('highlights the "start" and "end" keywords', function() { const {tokens} = grammar.tokenizeLine('a{ before: steps(0, start); after: steps(1, end); }'); expect(tokens[6]).toEqual({value: 'steps', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -3310,7 +3304,7 @@ a{ expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css']}); expect(tokens[11]).toEqual({value: 'start', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[23]).toEqual({value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); + expect(tokens[23]).toEqual({value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); }); }); @@ -3331,7 +3325,7 @@ a{ expect(tokens[5]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); expect(tokens[6]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[8]).toEqual({value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); - return expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('allows injected comments', function() { @@ -3342,10 +3336,10 @@ a{ expect(tokens[10]).toEqual({value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css']}); expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[13]).toEqual({value: '--something', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); - return expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('tokenises fallback values', function() { + it('tokenises fallback values', function() { const {tokens} = grammar.tokenizeLine('.bar{ width: var(--page-width, /*;;;);*/ 2); }'); expect(tokens[7]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); expect(tokens[8]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -3356,11 +3350,11 @@ a{ expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[16]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'constant.numeric.css']}); expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[18]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[18]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); }); }); - return it('does not tokenise functions with whitespace between name and parameters', function() { + it('does not tokenise functions with whitespace between name and parameters', function() { let {tokens} = grammar.tokenizeLine('a{ p: attr (title); }'); expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); @@ -3415,14 +3409,14 @@ a{ expect(tokens[11]).toEqual({value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[13]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[15]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[15]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); - return describe('Unicode ranges', function() { + describe('Unicode ranges', function() { it('tokenises single codepoints', function() { const {tokens} = grammar.tokenizeLine('a{ a: U+A5 }'); - return expect(tokens[6]).toEqual({value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[6]).toEqual({value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); it('tokenises codepoint ranges', function() { @@ -3434,10 +3428,10 @@ a{ ({tokens} = grammar.tokenizeLine('a{ unicode-range: u+0-7F }')); expect(tokens[6]).toEqual({value: 'u+0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); - return expect(tokens[8]).toEqual({value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[8]).toEqual({value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); - return it('tokenises wildcard ranges', function() { + it('tokenises wildcard ranges', function() { let {tokens} = grammar.tokenizeLine('a{ unicode-range: U+4?? }'); expect(tokens[6]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); @@ -3446,7 +3440,7 @@ a{ expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); expect(tokens[8]).toEqual({value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); - return expect(tokens[11]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[11]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); }); }); @@ -3464,7 +3458,7 @@ a{ expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); - return expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css']}); }); it('tokenizes escape sequences in double-quoted strings', function() { @@ -3478,7 +3472,7 @@ a{ expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); - return expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css']}); }); it('tokenises escape sequences in selectors', function() { @@ -3496,7 +3490,7 @@ a{ expect(tokens[4]).toEqual({value: '\\@', scopes: ['source.css', 'constant.character.escape.css']}); expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css']}); - return expect(tokens[7]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises escape sequences in property lists', function() { @@ -3506,14 +3500,14 @@ a{ expect(tokens[6]).toEqual({value: '\\64', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); expect(tokens[7]).toEqual({value: '\\74', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); expect(tokens[8]).toEqual({value: '\\68', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); - return expect(tokens[9]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[9]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); }); - return it('tokenises escape sequences in property values', function() { + it('tokenises escape sequences in property values', function() { const {tokens} = grammar.tokenizeLine('a { content: \\1F764; }'); expect(tokens[7]).toEqual({value: '\\1F764', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.character.escape.codepoint.css']}); expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3527,7 +3521,7 @@ a{ ({tokens} = grammar.tokenizeLine('a{ content: "aaaa')); expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); - return expect(tokens[7]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); + expect(tokens[7]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); }); it("knows when a string is line-wrapped", function() { @@ -3561,7 +3555,7 @@ aaa'; color: red; expect(lines[2][0]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css']}); expect(lines[2][1]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); expect(lines[2][2]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[2][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[2][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); }); it('highlights escape sequences inside invalid strings', function() { @@ -3575,10 +3569,10 @@ aaa'; color: red; expect(tokens[6]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[7]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); expect(tokens[8]).toEqual({value: "\\'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css']}); - return expect(tokens[9]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); + expect(tokens[9]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); }); - return it('highlights unclosed lines in line-wrapped strings', function() { + it('highlights unclosed lines in line-wrapped strings', function() { const lines = grammar.tokenizeLines(`\ a{ content: "aaa\\"aa\\ @@ -3599,7 +3593,7 @@ aaaa; color: red; expect(lines[3][4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[3][6]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); expect(lines[3][7]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3643,7 +3637,7 @@ aaaa; color: red; expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[13]).toEqual({value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('tokenises comments inside @font-face statements', function() { @@ -3654,7 +3648,7 @@ aaaa; color: red; expect(tokens[3]).toEqual({value: '"{;}"', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css']}); expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes comments before media queries', function() { @@ -3664,7 +3658,7 @@ aaaa; color: red; expect(tokens[1]).toEqual({value: ' comment ', scopes: ['source.css', 'comment.block.css']}); expect(tokens[2]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[4]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); - return expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); }); it('tokenizes comments after media queries', function() { @@ -3674,7 +3668,7 @@ aaaa; color: red; expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[3]).toEqual({value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); - return expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); }); it('tokenizes comments inside query lists', function() { @@ -3690,7 +3684,7 @@ aaaa; color: red; expect(tokens[9]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[10]).toEqual({value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); }); it('tokenizes inline comments', function() { @@ -3706,10 +3700,10 @@ aaaa; color: red; expect(tokens[7]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[8]).toEqual({value: 'padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); expect(tokens[9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it('tokenizes multi-line comments', function() { + it('tokenizes multi-line comments', function() { const lines = grammar.tokenizeLines(`\ section { border:4px /*1px; @@ -3725,7 +3719,7 @@ aaaa; color: red; expect(lines[2][0]).toEqual({value: ' padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); expect(lines[2][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3738,7 +3732,7 @@ animation-name: line-scale; ` ); expect(tokens[1][4]).toEqual({value: 'orphan-black', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); - return expect(tokens[2][4]).toEqual({value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[2][4]).toEqual({value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); })); describe('Transforms', () => it('tokenizes transform functions', function() { @@ -3760,7 +3754,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); expect(tokens[1][23]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[2][4]).toEqual({value: 'rotate', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); expect(tokens[2][10]).toEqual({value: 'translateX', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); - return expect(tokens[2][16]).toEqual({value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); + expect(tokens[2][16]).toEqual({value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); })); describe("performance regressions", function() { @@ -3768,10 +3762,10 @@ transform: rotate(90deg) translateX(100px) scale(1.5); grammar = atom.grammars.grammarForScopeName('source.css'); const start = Date.now(); grammar.tokenizeLine(' @@ -3779,7 +3773,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); \ ` ); - return expect(Date.now() - start).toBeLessThan(5000); + expect(Date.now() - start).toBeLessThan(5000); }); }); @@ -3829,7 +3823,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); })(); }); - return it("recognises Vim modelines", function() { + it("recognises Vim modelines", function() { let line; const valid = `\ vim: se filetype=css: @@ -3883,7 +3877,7 @@ _vi: se filetype=CSS: }); }); - return describe("Missing supported properties regressions", function() { + describe("Missing supported properties regressions", function() { it("recognises place-items property as supported", function() { const tokens = grammar.tokenizeLines('a { place-items: center center; }'); expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); @@ -3898,7 +3892,7 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("recognises place-self property as supported", function() { @@ -3915,7 +3909,7 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("recognises place-content property as supported", function() { @@ -3932,10 +3926,10 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it("recognises row-gap property as supported", function() { + it("recognises row-gap property as supported", function() { const tokens = grammar.tokenizeLines('a { row-gap: 5px; }'); expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.css']}); @@ -3948,7 +3942,7 @@ _vi: se filetype=CSS: expect(tokens[0][8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[0][9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][10]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - return expect(tokens[0][11]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[0][11]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); }); From db8ea2e5f139fdc0b562fb20c2e6c249e26f8dc5 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 18:12:07 -0700 Subject: [PATCH 08/18] Decaf `language-gfm` --- packages/language-gfm/spec/gfm-spec.coffee | 897 --------------------- packages/language-gfm/spec/gfm-spec.js | 115 ++- 2 files changed, 55 insertions(+), 957 deletions(-) delete mode 100644 packages/language-gfm/spec/gfm-spec.coffee diff --git a/packages/language-gfm/spec/gfm-spec.coffee b/packages/language-gfm/spec/gfm-spec.coffee deleted file mode 100644 index 9ba3e60b90..0000000000 --- a/packages/language-gfm/spec/gfm-spec.coffee +++ /dev/null @@ -1,897 +0,0 @@ -describe "GitHub Flavored Markdown grammar", -> - grammar = null - - beforeEach -> - waitsForPromise -> - atom.packages.activatePackage("language-gfm") - - runs -> - grammar = atom.grammars.grammarForScopeName("source.gfm") - - it "parses the grammar", -> - expect(grammar).toBeDefined() - expect(grammar.scopeName).toBe "source.gfm" - - it "tokenizes spaces", -> - {tokens} = grammar.tokenizeLine(" ") - expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"] - - it "tokenizes horizontal rules", -> - {tokens} = grammar.tokenizeLine("***") - expect(tokens[0]).toEqual value: "***", scopes: ["source.gfm", "comment.hr.gfm"] - - {tokens} = grammar.tokenizeLine("---") - expect(tokens[0]).toEqual value: "---", scopes: ["source.gfm", "comment.hr.gfm"] - - {tokens} = grammar.tokenizeLine("___") - expect(tokens[0]).toEqual value: "___", scopes: ["source.gfm", "comment.hr.gfm"] - - it "tokenizes escaped characters", -> - {tokens} = grammar.tokenizeLine("\\*") - expect(tokens[0]).toEqual value: "\\*", scopes: ["source.gfm", "constant.character.escape.gfm"] - - {tokens} = grammar.tokenizeLine("\\\\") - expect(tokens[0]).toEqual value: "\\\\", scopes: ["source.gfm", "constant.character.escape.gfm"] - - {tokens} = grammar.tokenizeLine("\\abc") - expect(tokens[0]).toEqual value: "\\a", scopes: ["source.gfm", "constant.character.escape.gfm"] - expect(tokens[1]).toEqual value: "bc", scopes: ["source.gfm"] - - it "tokenizes ***bold italic*** text", -> - {tokens} = grammar.tokenizeLine("this is ***bold italic*** text") - expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[2]).toEqual value: "bold italic", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[3]).toEqual value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[4]).toEqual value: " text", scopes: ["source.gfm"] - - [firstLineTokens, secondLineTokens] = grammar.tokenizeLines("this is ***bold\nitalic***!") - expect(firstLineTokens[0]).toEqual value: "this is ", scopes: ["source.gfm"] - expect(firstLineTokens[1]).toEqual value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(firstLineTokens[2]).toEqual value: "bold", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(secondLineTokens[0]).toEqual value: "italic", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(secondLineTokens[1]).toEqual value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(secondLineTokens[2]).toEqual value: "!", scopes: ["source.gfm"] - - it "tokenizes ___bold italic___ text", -> - {tokens} = grammar.tokenizeLine("this is ___bold italic___ text") - expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[2]).toEqual value: "bold italic", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[3]).toEqual value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[4]).toEqual value: " text", scopes: ["source.gfm"] - - [firstLineTokens, secondLineTokens] = grammar.tokenizeLines("this is ___bold\nitalic___!") - expect(firstLineTokens[0]).toEqual value: "this is ", scopes: ["source.gfm"] - expect(firstLineTokens[1]).toEqual value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(firstLineTokens[2]).toEqual value: "bold", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(secondLineTokens[0]).toEqual value: "italic", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(secondLineTokens[1]).toEqual value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(secondLineTokens[2]).toEqual value: "!", scopes: ["source.gfm"] - - it "tokenizes **bold** text", -> - {tokens} = grammar.tokenizeLine("**bold**") - expect(tokens[0]).toEqual value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[1]).toEqual value: "bold", scopes: ["source.gfm", "markup.bold.gfm"] - expect(tokens[2]).toEqual value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"] - - [firstLineTokens, secondLineTokens] = grammar.tokenizeLines("this is **not\nbold**!") - expect(firstLineTokens[0]).toEqual value: "this is **not", scopes: ["source.gfm"] - expect(secondLineTokens[0]).toEqual value: "bold**!", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("not**bold**") - expect(tokens[0]).toEqual value: "not", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[2]).toEqual value: "bold", scopes: ["source.gfm", "markup.bold.gfm"] - expect(tokens[3]).toEqual value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"] - - it "tokenizes __bold__ text", -> - {tokens} = grammar.tokenizeLine("____") - expect(tokens[0]).toEqual value: "____", scopes: ["source.gfm", "comment.hr.gfm"] - - {tokens} = grammar.tokenizeLine("__bold__") - expect(tokens[0]).toEqual value: "__", scopes: [ 'source.gfm', 'markup.bold.gfm', 'punctuation.definition.entity.gfm' ] - expect(tokens[1]).toEqual value: "bold", scopes: ["source.gfm", "markup.bold.gfm"] - expect(tokens[2]).toEqual value: "__", scopes: [ 'source.gfm', 'markup.bold.gfm', 'punctuation.definition.entity.gfm' ] - - [firstLineTokens, secondLineTokens] = grammar.tokenizeLines("this is __not\nbold__!") - expect(firstLineTokens[0]).toEqual value: "this is __not", scopes: ["source.gfm"] - expect(secondLineTokens[0]).toEqual value: "bold__!", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("not__bold__") - expect(tokens[0]).toEqual value: "not__bold__", scopes: ["source.gfm"] - - it "tokenizes *italic* text", -> - {tokens} = grammar.tokenizeLine("**") - expect(tokens[0]).toEqual value: "**", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("this is *italic* text") - expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "*", scopes: [ "source.gfm", "markup.italic.gfm", "punctuation.definition.entity.gfm" ] - expect(tokens[2]).toEqual value: "italic", scopes: ["source.gfm", "markup.italic.gfm"] - expect(tokens[3]).toEqual value: "*", scopes: [ "source.gfm", "markup.italic.gfm", "punctuation.definition.entity.gfm" ] - expect(tokens[4]).toEqual value: " text", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("is*italic*") - expect(tokens[0]).toEqual value: "is", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "*", scopes: [ "source.gfm", "markup.italic.gfm", "punctuation.definition.entity.gfm" ] - expect(tokens[2]).toEqual value: "italic", scopes: ["source.gfm", "markup.italic.gfm"] - expect(tokens[3]).toEqual value: "*", scopes: [ "source.gfm", "markup.italic.gfm", "punctuation.definition.entity.gfm" ] - - {tokens} = grammar.tokenizeLine("* not italic") - expect(tokens[0]).toEqual value: "*", scopes: ["source.gfm", "variable.unordered.list.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[2]).toEqual value: "not italic", scopes: ["source.gfm"] - - [firstLineTokens, secondLineTokens] = grammar.tokenizeLines("this is *not\nitalic*!") - expect(firstLineTokens[0]).toEqual value: "this is *not", scopes: ["source.gfm"] - expect(secondLineTokens[0]).toEqual value: "italic*!", scopes: ["source.gfm"] - - it "tokenizes _italic_ text", -> - {tokens} = grammar.tokenizeLine("__") - expect(tokens[0]).toEqual value: "__", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("this is _italic_ text") - expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ] - expect(tokens[2]).toEqual value: "italic", scopes: ["source.gfm", "markup.italic.gfm"] - expect(tokens[3]).toEqual value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ] - expect(tokens[4]).toEqual value: " text", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("not_italic_") - expect(tokens[0]).toEqual value: "not_italic_", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("not x^{a}_m y^{b}_n italic") - expect(tokens[0]).toEqual value: "not x^{a}_m y^{b}_n italic", scopes: ["source.gfm"] - - [firstLineTokens, secondLineTokens] = grammar.tokenizeLines("this is _not\nitalic_!") - expect(firstLineTokens[0]).toEqual value: "this is _not", scopes: ["source.gfm"] - expect(secondLineTokens[0]).toEqual value: "italic_!", scopes: ["source.gfm"] - - it "tokenizes ~~strike~~ text", -> - {tokens} = grammar.tokenizeLine("~~strike~~") - expect(tokens[0]).toEqual value: "~~", scopes: ["source.gfm", "markup.strike.gfm"] - expect(tokens[1]).toEqual value: "strike", scopes: ["source.gfm", "markup.strike.gfm"] - expect(tokens[2]).toEqual value: "~~", scopes: ["source.gfm", "markup.strike.gfm"] - - [firstLineTokens, secondLineTokens] = grammar.tokenizeLines("this is ~~str\nike~~!") - expect(firstLineTokens[0]).toEqual value: "this is ", scopes: ["source.gfm"] - expect(firstLineTokens[1]).toEqual value: "~~", scopes: ["source.gfm", "markup.strike.gfm"] - expect(firstLineTokens[2]).toEqual value: "str", scopes: ["source.gfm", "markup.strike.gfm"] - expect(secondLineTokens[0]).toEqual value: "ike", scopes: ["source.gfm", "markup.strike.gfm"] - expect(secondLineTokens[1]).toEqual value: "~~", scopes: ["source.gfm", "markup.strike.gfm"] - expect(secondLineTokens[2]).toEqual value: "!", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("not~~strike~~") - expect(tokens[0]).toEqual value: "not~~strike~~", scopes: ["source.gfm"] - - it "tokenizes headings", -> - {tokens} = grammar.tokenizeLine("# Heading 1") - expect(tokens[0]).toEqual value: "#", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.marker.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.space.gfm"] - expect(tokens[2]).toEqual value: "Heading 1", scopes: ["source.gfm", "markup.heading.heading-1.gfm"] - - {tokens} = grammar.tokenizeLine("## Heading 2") - expect(tokens[0]).toEqual value: "##", scopes: ["source.gfm", "markup.heading.heading-2.gfm", "markup.heading.marker.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm", "markup.heading.heading-2.gfm", "markup.heading.space.gfm"] - expect(tokens[2]).toEqual value: "Heading 2", scopes: ["source.gfm", "markup.heading.heading-2.gfm"] - - {tokens} = grammar.tokenizeLine("### Heading 3") - expect(tokens[0]).toEqual value: "###", scopes: ["source.gfm", "markup.heading.heading-3.gfm", "markup.heading.marker.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm", "markup.heading.heading-3.gfm", "markup.heading.space.gfm"] - expect(tokens[2]).toEqual value: "Heading 3", scopes: ["source.gfm", "markup.heading.heading-3.gfm"] - - {tokens} = grammar.tokenizeLine("#### Heading 4") - expect(tokens[0]).toEqual value: "####", scopes: ["source.gfm", "markup.heading.heading-4.gfm", "markup.heading.marker.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm", "markup.heading.heading-4.gfm", "markup.heading.space.gfm"] - expect(tokens[2]).toEqual value: "Heading 4", scopes: ["source.gfm", "markup.heading.heading-4.gfm"] - - {tokens} = grammar.tokenizeLine("##### Heading 5") - expect(tokens[0]).toEqual value: "#####", scopes: ["source.gfm", "markup.heading.heading-5.gfm", "markup.heading.marker.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm", "markup.heading.heading-5.gfm", "markup.heading.space.gfm"] - expect(tokens[2]).toEqual value: "Heading 5", scopes: ["source.gfm", "markup.heading.heading-5.gfm"] - - {tokens} = grammar.tokenizeLine("###### Heading 6") - expect(tokens[0]).toEqual value: "######", scopes: ["source.gfm", "markup.heading.heading-6.gfm", "markup.heading.marker.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm", "markup.heading.heading-6.gfm", "markup.heading.space.gfm"] - expect(tokens[2]).toEqual value: "Heading 6", scopes: ["source.gfm", "markup.heading.heading-6.gfm"] - - it "tokenizes matches inside of headers", -> - {tokens} = grammar.tokenizeLine("# Heading :one:") - expect(tokens[0]).toEqual value: "#", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.marker.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.space.gfm"] - expect(tokens[2]).toEqual value: "Heading ", scopes: ["source.gfm", "markup.heading.heading-1.gfm"] - expect(tokens[3]).toEqual value: ":", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.start.gfm"] - expect(tokens[4]).toEqual value: "one", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.word.gfm"] - expect(tokens[5]).toEqual value: ":", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.end.gfm"] - - it "tokenizes an :emoji:", -> - {tokens} = grammar.tokenizeLine("this is :no_good:") - expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: ":", scopes: ["source.gfm", "string.emoji.gfm", "string.emoji.start.gfm"] - expect(tokens[2]).toEqual value: "no_good", scopes: ["source.gfm", "string.emoji.gfm", "string.emoji.word.gfm"] - expect(tokens[3]).toEqual value: ":", scopes: ["source.gfm", "string.emoji.gfm", "string.emoji.end.gfm"] - - {tokens} = grammar.tokenizeLine("this is :no good:") - expect(tokens[0]).toEqual value: "this is :no good:", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("http://localhost:8080") - expect(tokens[0]).toEqual value: "http://localhost:8080", scopes: ["source.gfm"] - - it "tokenizes a ``` code block", -> - {tokens, ruleStack} = grammar.tokenizeLine("```") - expect(tokens[0]).toEqual value: "```", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"] - {tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack) - expect(tokens[0]).toEqual value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"] - {tokens} = grammar.tokenizeLine("```", ruleStack) - expect(tokens[0]).toEqual value: "```", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"] - - it "tokenizes a ~~~ code block", -> - {tokens, ruleStack} = grammar.tokenizeLine("~~~") - expect(tokens[0]).toEqual value: "~~~", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"] - {tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack) - expect(tokens[0]).toEqual value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"] - {tokens} = grammar.tokenizeLine("~~~", ruleStack) - expect(tokens[0]).toEqual value: "~~~", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"] - - it "doesn't tokenise ~`~ as a code block", -> - {tokens} = grammar.tokenizeLine("~`~") - expect(tokens[0]).toEqual value: '~', scopes: ['source.gfm'] - expect(tokens[1]).toEqual value: '`', scopes: ['source.gfm', 'markup.raw.gfm'] - expect(tokens[2]).toEqual value: '~', scopes: ['source.gfm', 'markup.raw.gfm'] - - it "tokenises code-blocks with borders of differing lengths", -> - [firstLineTokens, secondLineTokens, thirdLineTokens] = grammar.tokenizeLines("~~~\nfoo bar\n~~~~~~~") - expect(firstLineTokens[0]).toEqual value: '~~~', scopes: ['source.gfm', 'markup.raw.gfm', 'support.gfm'] - expect(secondLineTokens[0]).toEqual value: 'foo bar', scopes: ['source.gfm', 'markup.raw.gfm'] - expect(thirdLineTokens[0]).toEqual value: '~~~~~~~', scopes: ['source.gfm', 'markup.raw.gfm', 'support.gfm'] - - [firstLineTokens, secondLineTokens, thirdLineTokens] = grammar.tokenizeLines("~~~~~~~\nfoo bar\n~~~") - expect(firstLineTokens[0]).toEqual value: '~~~~~~~', scopes: ['source.gfm', 'markup.raw.gfm', 'support.gfm'] - expect(secondLineTokens[0]).toEqual value: 'foo bar', scopes: ['source.gfm', 'markup.raw.gfm'] - expect(thirdLineTokens[0]).toEqual value: '~~~', scopes: ['source.gfm', 'markup.raw.gfm'] - - it "tokenizes a ``` code block with trailing whitespace", -> - {tokens, ruleStack} = grammar.tokenizeLine("```") - expect(tokens[0]).toEqual value: "```", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"] - {tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack) - expect(tokens[0]).toEqual value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"] - {tokens} = grammar.tokenizeLine("``` ", ruleStack) - expect(tokens[0]).toEqual value: "``` ", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"] - - it "tokenizes a ~~~ code block with trailing whitespace", -> - {tokens, ruleStack} = grammar.tokenizeLine("~~~") - expect(tokens[0]).toEqual value: "~~~", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"] - {tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack) - expect(tokens[0]).toEqual value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"] - {tokens} = grammar.tokenizeLine("~~~ ", ruleStack) - expect(tokens[0]).toEqual value: "~~~ ", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"] - - it "tokenises a ``` code block with an unknown language", -> - {tokens, ruleStack} = grammar.tokenizeLine("``` myLanguage") - expect(tokens[0]).toEqual value: '``` myLanguage', scopes: ['source.gfm', 'markup.code.other.gfm', 'support.gfm'] - - {tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack) - expect(tokens[0]).toEqual value: "-> 'hello'", scopes: ['source.gfm', 'markup.code.other.gfm', 'source.embedded.mylanguage'] - - {tokens} = grammar.tokenizeLine("```", ruleStack) - expect(tokens[0]).toEqual value: '```', scopes: ['source.gfm', 'markup.code.other.gfm', 'support.gfm'] - - it "tokenizes a ``` code block with a known language", -> - {tokens, ruleStack} = grammar.tokenizeLine("``` bash") - expect(tokens[0]).toEqual value: "``` bash", scopes: ["source.gfm", "markup.code.shell.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.shell" - - {tokens, ruleStack} = grammar.tokenizeLine("```js ") - expect(tokens[0]).toEqual value: "```js ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.js" - - {tokens, ruleStack} = grammar.tokenizeLine("```JS ") - expect(tokens[0]).toEqual value: "```JS ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.js" - - {tokens, ruleStack} = grammar.tokenizeLine("```r ") - expect(tokens[0]).toEqual value: "```r ", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.r" - - {tokens, ruleStack} = grammar.tokenizeLine("```properties ") - expect(tokens[0]).toEqual value: "```properties ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.git-config" - - it "tokenizes a Rmarkdown ``` code block", -> - {tokens, ruleStack} = grammar.tokenizeLine("```{r}") - expect(tokens[0]).toEqual value: "```{r}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.r" - - {tokens, ruleStack} = grammar.tokenizeLine("```{r,eval=TRUE,cache=FALSE}") - expect(tokens[0]).toEqual value: "```{r,eval=TRUE,cache=FALSE}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.r" - - {tokens, ruleStack} = grammar.tokenizeLine("```{r eval=TRUE,cache=FALSE}") - expect(tokens[0]).toEqual value: "```{r eval=TRUE,cache=FALSE}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.r" - - it "tokenizes a Rmarkdown ``` code block with whitespace", -> - {tokens, ruleStack} = grammar.tokenizeLine("```{r }") - expect(tokens[0]).toEqual value: "```{r }", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.r" - - {tokens, ruleStack} = grammar.tokenizeLine("```{R } ") - expect(tokens[0]).toEqual value: "```{R } ", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.r" - - {tokens, ruleStack} = grammar.tokenizeLine("```{r eval = TRUE, cache = FALSE}") - expect(tokens[0]).toEqual value: "```{r eval = TRUE, cache = FALSE}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.r" - - it "tokenizes a ~~~ code block with a language", -> - {tokens, ruleStack} = grammar.tokenizeLine("~~~ bash") - expect(tokens[0]).toEqual value: "~~~ bash", scopes: ["source.gfm", "markup.code.shell.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.shell" - - {tokens, ruleStack} = grammar.tokenizeLine("~~~js ") - expect(tokens[0]).toEqual value: "~~~js ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.js" - - {tokens, ruleStack} = grammar.tokenizeLine("~~~properties ") - expect(tokens[0]).toEqual value: "~~~properties ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.git-config" - - it "tokenizes a ``` code block with a language and trailing whitespace", -> - {tokens, ruleStack} = grammar.tokenizeLine("``` bash") - {tokens} = grammar.tokenizeLine("``` ", ruleStack) - expect(tokens[0]).toEqual value: "``` ", scopes: ["source.gfm", "markup.code.shell.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.shell" - - {tokens, ruleStack} = grammar.tokenizeLine("```js ") - {tokens} = grammar.tokenizeLine("``` ", ruleStack) - expect(tokens[0]).toEqual value: "``` ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.js" - - it "tokenizes a ~~~ code block with a language and trailing whitespace", -> - {tokens, ruleStack} = grammar.tokenizeLine("~~~ bash") - {tokens} = grammar.tokenizeLine("~~~ ", ruleStack) - expect(tokens[0]).toEqual value: "~~~ ", scopes: ["source.gfm", "markup.code.shell.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.shell" - - {tokens, ruleStack} = grammar.tokenizeLine("~~~js ") - {tokens} = grammar.tokenizeLine("~~~ ", ruleStack) - expect(tokens[0]).toEqual value: "~~~ ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.js" - - {tokens, ruleStack} = grammar.tokenizeLine("~~~ properties ") - {tokens} = grammar.tokenizeLine("~~~ ", ruleStack) - expect(tokens[0]).toEqual value: "~~~ ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"] - expect(ruleStack[1].contentScopeName).toBe "source.embedded.git-config" - - it "tokenizes inline `code` blocks", -> - {tokens} = grammar.tokenizeLine("`this` is `code`") - expect(tokens[0]).toEqual value: "`", scopes: ["source.gfm", "markup.raw.gfm"] - expect(tokens[1]).toEqual value: "this", scopes: ["source.gfm", "markup.raw.gfm"] - expect(tokens[2]).toEqual value: "`", scopes: ["source.gfm", "markup.raw.gfm"] - expect(tokens[3]).toEqual value: " is ", scopes: ["source.gfm"] - expect(tokens[4]).toEqual value: "`", scopes: ["source.gfm", "markup.raw.gfm"] - expect(tokens[5]).toEqual value: "code", scopes: ["source.gfm", "markup.raw.gfm"] - expect(tokens[6]).toEqual value: "`", scopes: ["source.gfm", "markup.raw.gfm"] - - {tokens} = grammar.tokenizeLine("``") - expect(tokens[0]).toEqual value: "`", scopes: ["source.gfm", "markup.raw.gfm"] - expect(tokens[1]).toEqual value: "`", scopes: ["source.gfm", "markup.raw.gfm"] - - {tokens} = grammar.tokenizeLine("``a\\`b``") - expect(tokens[0]).toEqual value: "``", scopes: ["source.gfm", "markup.raw.gfm"] - expect(tokens[1]).toEqual value: "a\\`b", scopes: ["source.gfm", "markup.raw.gfm"] - expect(tokens[2]).toEqual value: "``", scopes: ["source.gfm", "markup.raw.gfm"] - - it "tokenizes [links](links)", -> - {tokens} = grammar.tokenizeLine("please click [this link](website)") - expect(tokens[0]).toEqual value: "please click ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[2]).toEqual value: "this link", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[3]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[4]).toEqual value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[5]).toEqual value: "website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[6]).toEqual value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - - it "tokenizes reference [links][links]", -> - {tokens} = grammar.tokenizeLine("please click [this link][website]") - expect(tokens[0]).toEqual value: "please click ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[2]).toEqual value: "this link", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[3]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[4]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[5]).toEqual value: "website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[6]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - - it "tokenizes id-less reference [links][]", -> - {tokens} = grammar.tokenizeLine("please click [this link][]") - expect(tokens[0]).toEqual value: "please click ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[2]).toEqual value: "this link", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[3]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[4]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[5]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - - it "tokenizes [link]: footers", -> - {tokens} = grammar.tokenizeLine("[aLink]: http://website") - expect(tokens[0]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[1]).toEqual value: "aLink", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[2]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[3]).toEqual value: ":", scopes: ["source.gfm", "link", "punctuation.separator.key-value.gfm"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.gfm", "link"] - expect(tokens[5]).toEqual value: "http://website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - - it "tokenizes [link]: ", -> - {tokens} = grammar.tokenizeLine("[aLink]: ") - expect(tokens[0]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[1]).toEqual value: "aLink", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[2]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[3]).toEqual value: ": <", scopes: ["source.gfm", "link"] - expect(tokens[4]).toEqual value: "http://website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[5]).toEqual value: ">", scopes: ["source.gfm", "link"] - - it "tokenizes [![links](links)](links)", -> - {tokens} = grammar.tokenizeLine("[![title](image)](link)") - expect(tokens[0]).toEqual value: "[!", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[1]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[2]).toEqual value: "title", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[3]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[4]).toEqual value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[5]).toEqual value: "image", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[6]).toEqual value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[7]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[8]).toEqual value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[9]).toEqual value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[10]).toEqual value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - - it "tokenizes [![links](links)][links]", -> - {tokens} = grammar.tokenizeLine("[![title](image)][link]") - expect(tokens[0]).toEqual value: "[!", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[1]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[2]).toEqual value: "title", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[3]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[4]).toEqual value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[5]).toEqual value: "image", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[6]).toEqual value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[7]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[8]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[9]).toEqual value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[10]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - - it "tokenizes [![links][links]](links)", -> - {tokens} = grammar.tokenizeLine("[![title][image]](link)") - expect(tokens[0]).toEqual value: "[!", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[1]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[2]).toEqual value: "title", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[3]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[4]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[5]).toEqual value: "image", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[6]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[7]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[8]).toEqual value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[9]).toEqual value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[10]).toEqual value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - - it "tokenizes [![links][links]][links]", -> - {tokens} = grammar.tokenizeLine("[![title][image]][link]") - expect(tokens[0]).toEqual value: "[!", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[1]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[2]).toEqual value: "title", scopes: ["source.gfm", "link", "entity.gfm"] - expect(tokens[3]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[4]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[5]).toEqual value: "image", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[6]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[7]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - expect(tokens[8]).toEqual value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"] - expect(tokens[9]).toEqual value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"] - expect(tokens[10]).toEqual value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"] - - it "tokenizes mentions", -> - {tokens} = grammar.tokenizeLine("sentence with no space before@name ") - expect(tokens[0]).toEqual value: "sentence with no space before@name ", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("@name '@name' @name's @name. @name, (@name) [@name]") - expect(tokens[0]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[1]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[2]).toEqual value: " '", scopes: ["source.gfm"] - expect(tokens[3]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[4]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[5]).toEqual value: "' ", scopes: ["source.gfm"] - expect(tokens[6]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[7]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[8]).toEqual value: "'s ", scopes: ["source.gfm"] - expect(tokens[9]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[10]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[11]).toEqual value: ". ", scopes: ["source.gfm"] - expect(tokens[12]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[13]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[14]).toEqual value: ", (", scopes: ["source.gfm"] - expect(tokens[15]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[16]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[17]).toEqual value: ") [", scopes: ["source.gfm"] - expect(tokens[18]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[19]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[20]).toEqual value: "]", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine('"@name"') - expect(tokens[0]).toEqual value: '"', scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[2]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[3]).toEqual value: '"', scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("sentence with a space before @name/ and an invalid symbol after") - expect(tokens[0]).toEqual value: "sentence with a space before @name/ and an invalid symbol after", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("sentence with a space before @name that continues") - expect(tokens[0]).toEqual value: "sentence with a space before ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[2]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[3]).toEqual value: " that continues", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("* @name at the start of an unordered list") - expect(tokens[0]).toEqual value: "*", scopes: ["source.gfm", "variable.unordered.list.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[2]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[3]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[4]).toEqual value: " at the start of an unordered list", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("a username @1337_hubot with numbers, letters and underscores") - expect(tokens[0]).toEqual value: "a username ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[2]).toEqual value: "1337_hubot", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[3]).toEqual value: " with numbers, letters and underscores", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("a username @1337-hubot with numbers, letters and hyphens") - expect(tokens[0]).toEqual value: "a username ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[2]).toEqual value: "1337-hubot", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[3]).toEqual value: " with numbers, letters and hyphens", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("@name at the start of a line") - expect(tokens[0]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[1]).toEqual value: "name", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[2]).toEqual value: " at the start of a line", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("any email like you@domain.com shouldn't mistakenly be matched as a mention") - expect(tokens[0]).toEqual value: "any email like you@domain.com shouldn't mistakenly be matched as a mention", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("@person's") - expect(tokens[0]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[1]).toEqual value: "person", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[2]).toEqual value: "'s", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("@person;") - expect(tokens[0]).toEqual value: "@", scopes: ["source.gfm", "variable.mention.gfm"] - expect(tokens[1]).toEqual value: "person", scopes: ["source.gfm", "string.username.gfm"] - expect(tokens[2]).toEqual value: ";", scopes: ["source.gfm"] - - it "tokenizes issue numbers", -> - {tokens} = grammar.tokenizeLine("sentence with no space before#12 ") - expect(tokens[0]).toEqual value: "sentence with no space before#12 ", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine(" #101 '#101' #101's #101. #101, (#101) [#101]") - expect(tokens[1]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[2]).toEqual value: "101", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[3]).toEqual value: " '", scopes: ["source.gfm"] - expect(tokens[4]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[5]).toEqual value: "101", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[6]).toEqual value: "' ", scopes: ["source.gfm"] - expect(tokens[7]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[8]).toEqual value: "101", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[9]).toEqual value: "'s ", scopes: ["source.gfm"] - expect(tokens[10]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[11]).toEqual value: "101", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[12]).toEqual value: ". ", scopes: ["source.gfm"] - expect(tokens[13]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[14]).toEqual value: "101", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[15]).toEqual value: ", (", scopes: ["source.gfm"] - expect(tokens[16]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[17]).toEqual value: "101", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[18]).toEqual value: ") [", scopes: ["source.gfm"] - expect(tokens[19]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[20]).toEqual value: "101", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[21]).toEqual value: "]", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine('"#101"') - expect(tokens[0]).toEqual value: '"', scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[2]).toEqual value: "101", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[3]).toEqual value: '"', scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("sentence with a space before #123i and a character after") - expect(tokens[0]).toEqual value: "sentence with a space before #123i and a character after", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine("sentence with a space before #123 that continues") - expect(tokens[0]).toEqual value: "sentence with a space before ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[2]).toEqual value: "123", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[3]).toEqual value: " that continues", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine(" #123's") - expect(tokens[1]).toEqual value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"] - expect(tokens[2]).toEqual value: "123", scopes: ["source.gfm", "string.issue.number.gfm"] - expect(tokens[3]).toEqual value: "'s", scopes: ["source.gfm"] - - it "tokenizes unordered lists", -> - {tokens} = grammar.tokenizeLine("*Item 1") - expect(tokens[0]).not.toEqual value: "*Item 1", scopes: ["source.gfm", "variable.unordered.list.gfm"] - - {tokens} = grammar.tokenizeLine(" * Item 1") - expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "*", scopes: ["source.gfm", "variable.unordered.list.gfm"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[3]).toEqual value: "Item 1", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine(" + Item 2") - expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "+", scopes: ["source.gfm", "variable.unordered.list.gfm"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[3]).toEqual value: "Item 2", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine(" - Item 3") - expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "-", scopes: ["source.gfm", "variable.unordered.list.gfm"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[3]).toEqual value: "Item 3", scopes: ["source.gfm"] - - it "tokenizes ordered lists", -> - {tokens} = grammar.tokenizeLine("1.First Item") - expect(tokens[0]).toEqual value: "1.First Item", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine(" 1. First Item") - expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "1.", scopes: ["source.gfm", "variable.ordered.list.gfm"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[3]).toEqual value: "First Item", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine(" 10. Tenth Item") - expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "10.", scopes: ["source.gfm", "variable.ordered.list.gfm"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[3]).toEqual value: "Tenth Item", scopes: ["source.gfm"] - - {tokens} = grammar.tokenizeLine(" 111. Hundred and eleventh item") - expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: "111.", scopes: ["source.gfm", "variable.ordered.list.gfm"] - expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"] - expect(tokens[3]).toEqual value: "Hundred and eleventh item", scopes: ["source.gfm"] - - it "tokenizes > quoted text", -> - {tokens} = grammar.tokenizeLine("> Quotation :+1:") - expect(tokens[0]).toEqual value: ">", scopes: ["source.gfm", "comment.quote.gfm", "support.quote.gfm"] - expect(tokens[1]).toEqual value: " Quotation :+1:", scopes: ["source.gfm", "comment.quote.gfm"] - - it "tokenizes HTML entities", -> - {tokens} = grammar.tokenizeLine("™ ™ &a1; ³") - expect(tokens[0]).toEqual value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[1]).toEqual value: "trade", scopes: ["source.gfm", "constant.character.entity.gfm"] - expect(tokens[2]).toEqual value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - - expect(tokens[3]).toEqual value: " ", scopes: ["source.gfm"] - - expect(tokens[4]).toEqual value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[5]).toEqual value: "#8482", scopes: ["source.gfm", "constant.character.entity.gfm"] - expect(tokens[6]).toEqual value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - - expect(tokens[7]).toEqual value: " ", scopes: ["source.gfm"] - - expect(tokens[8]).toEqual value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[9]).toEqual value: "a1", scopes: ["source.gfm", "constant.character.entity.gfm"] - expect(tokens[10]).toEqual value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - - expect(tokens[11]).toEqual value: " ", scopes: ["source.gfm"] - - expect(tokens[12]).toEqual value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[13]).toEqual value: "#xb3", scopes: ["source.gfm", "constant.character.entity.gfm"] - expect(tokens[14]).toEqual value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - - it "tokenizes HTML entities in *italic* text", -> - {tokens} = grammar.tokenizeLine("*™ ™ ³*") - expect(tokens[0]).toEqual value: "*", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ] - expect(tokens[1]).toEqual value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[2]).toEqual value: "trade", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[3]).toEqual value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.gfm", "markup.italic.gfm"] - expect(tokens[5]).toEqual value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[6]).toEqual value: "#8482", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[7]).toEqual value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.gfm", "markup.italic.gfm"] - expect(tokens[9]).toEqual value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[10]).toEqual value: "#xb3", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[11]).toEqual value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[12]).toEqual value: "*", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ] - - {tokens} = grammar.tokenizeLine("_™ ™ ³_") - expect(tokens[0]).toEqual value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ] - expect(tokens[1]).toEqual value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[2]).toEqual value: "trade", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[3]).toEqual value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.gfm", "markup.italic.gfm"] - expect(tokens[5]).toEqual value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[6]).toEqual value: "#8482", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[7]).toEqual value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.gfm", "markup.italic.gfm"] - expect(tokens[9]).toEqual value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[10]).toEqual value: "#xb3", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[11]).toEqual value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[12]).toEqual value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ] - - it "tokenizes HTML entities in **bold** text", -> - {tokens} = grammar.tokenizeLine("**™ ™ ³**") - expect(tokens[0]).toEqual value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[1]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[2]).toEqual value: "trade", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"] - expect(tokens[3]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.gfm", "markup.bold.gfm"] - expect(tokens[5]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[6]).toEqual value: "#8482", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"] - expect(tokens[7]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.gfm", "markup.bold.gfm"] - expect(tokens[9]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[10]).toEqual value: "#xb3", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"] - expect(tokens[11]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[12]).toEqual value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"] - - {tokens} = grammar.tokenizeLine("__™ ™ ³__") - expect(tokens[0]).toEqual value: "__", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[1]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[2]).toEqual value: "trade", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"] - expect(tokens[3]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.gfm", "markup.bold.gfm"] - expect(tokens[5]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[6]).toEqual value: "#8482", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"] - expect(tokens[7]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.gfm", "markup.bold.gfm"] - expect(tokens[9]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[10]).toEqual value: "#xb3", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"] - expect(tokens[11]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[12]).toEqual value: "__", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"] - - it "tokenizes HTML entities in ***bold italic*** text", -> - {tokens} = grammar.tokenizeLine("***™ ™ ³***") - expect(tokens[0]).toEqual value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[1]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[2]).toEqual value: "trade", scopes: [ "source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm" ] - expect(tokens[3]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[5]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[6]).toEqual value: "#8482", scopes: [ "source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm" ] - expect(tokens[7]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[9]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[10]).toEqual value: "#xb3", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[11]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[12]).toEqual value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"] - - {tokens} = grammar.tokenizeLine("___™ ™ ³___") - expect(tokens[0]).toEqual value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[1]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[2]).toEqual value: "trade", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[3]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[5]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[6]).toEqual value: "#8482", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[7]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.gfm", "markup.bold.italic.gfm"] - expect(tokens[9]).toEqual value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[10]).toEqual value: "#xb3", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[11]).toEqual value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"] - expect(tokens[12]).toEqual value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"] - - it "tokenizes HTML entities in strikethrough text", -> - {tokens} = grammar.tokenizeLine("~~™ ™ ³~~") - expect(tokens[0]).toEqual value: "~~", scopes: ["source.gfm", "markup.strike.gfm"] - expect(tokens[1]).toEqual value: "&", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[2]).toEqual value: "trade", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm"] - expect(tokens[3]).toEqual value: ";", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[4]).toEqual value: " ", scopes: ["source.gfm", "markup.strike.gfm"] - expect(tokens[5]).toEqual value: "&", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[6]).toEqual value: "#8482", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm"] - expect(tokens[7]).toEqual value: ";", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[8]).toEqual value: " ", scopes: ["source.gfm", "markup.strike.gfm"] - expect(tokens[9]).toEqual value: "&", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[10]).toEqual value: "#xb3", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm"] - expect(tokens[11]).toEqual value: ";", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"] - expect(tokens[12]).toEqual value: "~~", scopes: ["source.gfm", "markup.strike.gfm"] - - it "tokenizes HTML comments", -> - {tokens} = grammar.tokenizeLine("") - expect(tokens[0]).toEqual value: "", scopes: ["source.gfm", "comment.block.gfm", "punctuation.definition.comment.gfm"] - - it "tokenizes YAML front matter", -> - [firstLineTokens, secondLineTokens, thirdLineTokens] = grammar.tokenizeLines """ - --- - front: matter - --- - """ - - expect(firstLineTokens[0]).toEqual value: "---", scopes: ["source.gfm", "front-matter.yaml.gfm", "comment.hr.gfm"] - expect(secondLineTokens[0]).toEqual value: "front: matter", scopes: ["source.gfm", "front-matter.yaml.gfm"] - expect(thirdLineTokens[0]).toEqual value: "---", scopes: ["source.gfm", "front-matter.yaml.gfm", "comment.hr.gfm"] - - it "tokenizes linebreaks", -> - {tokens} = grammar.tokenizeLine("line ") - expect(tokens[0]).toEqual value: "line", scopes: ["source.gfm"] - expect(tokens[1]).toEqual value: " ", scopes: ["source.gfm", "linebreak.gfm"] - - it "tokenizes tables", -> - [headerTokens, alignTokens, contentTokens] = grammar.tokenizeLines """ - | Column 1 | Column 2 | - |:----------|:---------:| - | Content 1 | Content 2 | - """ - - # Header line - expect(headerTokens[0]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"] - expect(headerTokens[1]).toEqual value: " Column 1 ", scopes: ["source.gfm", "table.gfm"] - expect(headerTokens[2]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.inner"] - expect(headerTokens[3]).toEqual value: " Column 2 ", scopes: ["source.gfm", "table.gfm"] - expect(headerTokens[4]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"] - - # Alignment line - expect(alignTokens[0]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"] - expect(alignTokens[1]).toEqual value: ":", scopes: ["source.gfm", "table.gfm", "border.alignment"] - expect(alignTokens[2]).toEqual value: "----------", scopes: ["source.gfm", "table.gfm", "border.header"] - expect(alignTokens[3]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.inner"] - expect(alignTokens[4]).toEqual value: ":", scopes: ["source.gfm", "table.gfm", "border.alignment"] - expect(alignTokens[5]).toEqual value: "---------", scopes: ["source.gfm", "table.gfm", "border.header"] - expect(alignTokens[6]).toEqual value: ":", scopes: ["source.gfm", "table.gfm", "border.alignment"] - expect(alignTokens[7]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"] - - # Content line - expect(contentTokens[0]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"] - expect(contentTokens[1]).toEqual value: " Content 1 ", scopes: ["source.gfm", "table.gfm"] - expect(contentTokens[2]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.inner"] - expect(contentTokens[3]).toEqual value: " Content 2 ", scopes: ["source.gfm", "table.gfm"] - expect(contentTokens[4]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"] - - [headerTokens, emptyLineTokens, headingTokens] = grammar.tokenizeLines """ - | Column 1 | Column 2\t - - # Heading - """ - - expect(headerTokens[0]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.outer"] - expect(headerTokens[1]).toEqual value: " Column 1 ", scopes: ["source.gfm", "table.gfm"] - expect(headerTokens[2]).toEqual value: "|", scopes: ["source.gfm", "table.gfm", "border.pipe.inner"] - expect(headerTokens[3]).toEqual value: " Column 2", scopes: ["source.gfm", "table.gfm"] - expect(headerTokens[4]).toEqual value: "\t", scopes: ["source.gfm", "table.gfm"] - - expect(headingTokens[0]).toEqual value: "#", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.marker.gfm"] - expect(headingTokens[1]).toEqual value: " ", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.space.gfm"] - expect(headingTokens[2]).toEqual value: "Heading", scopes: ["source.gfm", "markup.heading.heading-1.gfm"] - - it "tokenizes criticmarkup", -> - [addToken, delToken, hlToken, subToken] = grammar.tokenizeLines """ - Add{++ some text++} - Delete{-- some text--} - Highlight {==some text==}{>>with comment<<} - Replace {~~this~>by that~~} - """ - # Addition - expect(addToken[0]).toEqual value: "Add", scopes: ["source.gfm"] - expect(addToken[1]).toEqual value: "{++", scopes: ["source.gfm", "markup.inserted.critic.gfm.addition", "punctuation.definition.inserted.critic.gfm.addition.marker"] - expect(addToken[2]).toEqual value: " some text", scopes: ["source.gfm", "markup.inserted.critic.gfm.addition"] - expect(addToken[3]).toEqual value: "++}", scopes: ["source.gfm", "markup.inserted.critic.gfm.addition", "punctuation.definition.inserted.critic.gfm.addition.marker"] - # Deletion - expect(delToken[0]).toEqual value: "Delete", scopes: ["source.gfm"] - expect(delToken[1]).toEqual value: "{--", scopes: ["source.gfm", "markup.deleted.critic.gfm.deletion", "punctuation.definition.deleted.critic.gfm.deletion.marker"] - expect(delToken[2]).toEqual value: " some text", scopes: ["source.gfm", "markup.deleted.critic.gfm.deletion"] - expect(delToken[3]).toEqual value: "--}", scopes: ["source.gfm", "markup.deleted.critic.gfm.deletion", "punctuation.definition.deleted.critic.gfm.deletion.marker"] - # Comment and highlight - expect(hlToken[0]).toEqual value: "Highlight ", scopes: ["source.gfm"] - expect(hlToken[1]).toEqual value: "{==", scopes: ["source.gfm", "critic.gfm.highlight", "critic.gfm.highlight.marker"] - expect(hlToken[2]).toEqual value: "some text", scopes: ["source.gfm", "critic.gfm.highlight"] - expect(hlToken[3]).toEqual value: "==}", scopes: ["source.gfm", "critic.gfm.highlight", "critic.gfm.highlight.marker"] - expect(hlToken[4]).toEqual value: "{>>", scopes: ["source.gfm", "critic.gfm.comment", "critic.gfm.comment.marker"] - expect(hlToken[5]).toEqual value: "with comment", scopes: ["source.gfm", "critic.gfm.comment"] - expect(hlToken[6]).toEqual value: "<<}", scopes: ["source.gfm", "critic.gfm.comment", "critic.gfm.comment.marker"] - # Replace - expect(subToken[0]).toEqual value: "Replace ", scopes: ["source.gfm"] - expect(subToken[1]).toEqual value: "{~~", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.marker"] - expect(subToken[2]).toEqual value: "this", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution"] - expect(subToken[3]).toEqual value: "~>", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.operator"] - expect(subToken[4]).toEqual value: "by that", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution"] - expect(subToken[5]).toEqual value: "~~}", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.marker"] diff --git a/packages/language-gfm/spec/gfm-spec.js b/packages/language-gfm/spec/gfm-spec.js index 733d14582a..231b88488a 100644 --- a/packages/language-gfm/spec/gfm-spec.js +++ b/packages/language-gfm/spec/gfm-spec.js @@ -1,26 +1,21 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe("GitHub Flavored Markdown grammar", function() { let grammar = null; beforeEach(function() { waitsForPromise(() => atom.packages.activatePackage("language-gfm")); - return runs(() => grammar = atom.grammars.grammarForScopeName("source.gfm")); + runs(() => grammar = atom.grammars.grammarForScopeName("source.gfm")); }); it("parses the grammar", function() { expect(grammar).toBeDefined(); - return expect(grammar.scopeName).toBe("source.gfm"); + expect(grammar.scopeName).toBe("source.gfm"); }); it("tokenizes spaces", function() { const {tokens} = grammar.tokenizeLine(" "); - return expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); + expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); }); it("tokenizes horizontal rules", function() { @@ -31,7 +26,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[0]).toEqual({value: "---", scopes: ["source.gfm", "comment.hr.gfm"]}); ({tokens} = grammar.tokenizeLine("___")); - return expect(tokens[0]).toEqual({value: "___", scopes: ["source.gfm", "comment.hr.gfm"]}); + expect(tokens[0]).toEqual({value: "___", scopes: ["source.gfm", "comment.hr.gfm"]}); }); it("tokenizes escaped characters", function() { @@ -43,7 +38,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens} = grammar.tokenizeLine("\\abc")); expect(tokens[0]).toEqual({value: "\\a", scopes: ["source.gfm", "constant.character.escape.gfm"]}); - return expect(tokens[1]).toEqual({value: "bc", scopes: ["source.gfm"]}); + expect(tokens[1]).toEqual({value: "bc", scopes: ["source.gfm"]}); }); it("tokenizes ***bold italic*** text", function() { @@ -60,7 +55,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(firstLineTokens[2]).toEqual({value: "bold", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); expect(secondLineTokens[0]).toEqual({value: "italic", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); expect(secondLineTokens[1]).toEqual({value: "***", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); - return expect(secondLineTokens[2]).toEqual({value: "!", scopes: ["source.gfm"]}); + expect(secondLineTokens[2]).toEqual({value: "!", scopes: ["source.gfm"]}); }); it("tokenizes ___bold italic___ text", function() { @@ -77,7 +72,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(firstLineTokens[2]).toEqual({value: "bold", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); expect(secondLineTokens[0]).toEqual({value: "italic", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); expect(secondLineTokens[1]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); - return expect(secondLineTokens[2]).toEqual({value: "!", scopes: ["source.gfm"]}); + expect(secondLineTokens[2]).toEqual({value: "!", scopes: ["source.gfm"]}); }); it("tokenizes **bold** text", function() { @@ -94,7 +89,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[0]).toEqual({value: "not", scopes: ["source.gfm"]}); expect(tokens[1]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); expect(tokens[2]).toEqual({value: "bold", scopes: ["source.gfm", "markup.bold.gfm"]}); - return expect(tokens[3]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[3]).toEqual({value: "**", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); }); it("tokenizes __bold__ text", function() { @@ -111,7 +106,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(secondLineTokens[0]).toEqual({value: "bold__!", scopes: ["source.gfm"]}); ({tokens} = grammar.tokenizeLine("not__bold__")); - return expect(tokens[0]).toEqual({value: "not__bold__", scopes: ["source.gfm"]}); + expect(tokens[0]).toEqual({value: "not__bold__", scopes: ["source.gfm"]}); }); it("tokenizes *italic* text", function() { @@ -138,7 +133,7 @@ describe("GitHub Flavored Markdown grammar", function() { const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is *not\nitalic*!")); expect(firstLineTokens[0]).toEqual({value: "this is *not", scopes: ["source.gfm"]}); - return expect(secondLineTokens[0]).toEqual({value: "italic*!", scopes: ["source.gfm"]}); + expect(secondLineTokens[0]).toEqual({value: "italic*!", scopes: ["source.gfm"]}); }); it("tokenizes _italic_ text", function() { @@ -160,7 +155,7 @@ describe("GitHub Flavored Markdown grammar", function() { const [firstLineTokens, secondLineTokens] = Array.from(grammar.tokenizeLines("this is _not\nitalic_!")); expect(firstLineTokens[0]).toEqual({value: "this is _not", scopes: ["source.gfm"]}); - return expect(secondLineTokens[0]).toEqual({value: "italic_!", scopes: ["source.gfm"]}); + expect(secondLineTokens[0]).toEqual({value: "italic_!", scopes: ["source.gfm"]}); }); it("tokenizes ~~strike~~ text", function() { @@ -178,7 +173,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(secondLineTokens[2]).toEqual({value: "!", scopes: ["source.gfm"]}); ({tokens} = grammar.tokenizeLine("not~~strike~~")); - return expect(tokens[0]).toEqual({value: "not~~strike~~", scopes: ["source.gfm"]}); + expect(tokens[0]).toEqual({value: "not~~strike~~", scopes: ["source.gfm"]}); }); it("tokenizes headings", function() { @@ -210,7 +205,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens} = grammar.tokenizeLine("###### Heading 6")); expect(tokens[0]).toEqual({value: "######", scopes: ["source.gfm", "markup.heading.heading-6.gfm", "markup.heading.marker.gfm"]}); expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-6.gfm", "markup.heading.space.gfm"]}); - return expect(tokens[2]).toEqual({value: "Heading 6", scopes: ["source.gfm", "markup.heading.heading-6.gfm"]}); + expect(tokens[2]).toEqual({value: "Heading 6", scopes: ["source.gfm", "markup.heading.heading-6.gfm"]}); }); it("tokenizes matches inside of headers", function() { @@ -220,7 +215,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[2]).toEqual({value: "Heading ", scopes: ["source.gfm", "markup.heading.heading-1.gfm"]}); expect(tokens[3]).toEqual({value: ":", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.start.gfm"]}); expect(tokens[4]).toEqual({value: "one", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.word.gfm"]}); - return expect(tokens[5]).toEqual({value: ":", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.end.gfm"]}); + expect(tokens[5]).toEqual({value: ":", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "string.emoji.gfm", "string.emoji.end.gfm"]}); }); it("tokenizes an :emoji:", function() { @@ -234,7 +229,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[0]).toEqual({value: "this is :no good:", scopes: ["source.gfm"]}); ({tokens} = grammar.tokenizeLine("http://localhost:8080")); - return expect(tokens[0]).toEqual({value: "http://localhost:8080", scopes: ["source.gfm"]}); + expect(tokens[0]).toEqual({value: "http://localhost:8080", scopes: ["source.gfm"]}); }); it("tokenizes a ``` code block", function() { @@ -243,7 +238,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]}); ({tokens} = grammar.tokenizeLine("```", ruleStack)); - return expect(tokens[0]).toEqual({value: "```", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); + expect(tokens[0]).toEqual({value: "```", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); }); it("tokenizes a ~~~ code block", function() { @@ -252,14 +247,14 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]}); ({tokens} = grammar.tokenizeLine("~~~", ruleStack)); - return expect(tokens[0]).toEqual({value: "~~~", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); + expect(tokens[0]).toEqual({value: "~~~", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); }); it("doesn't tokenise ~`~ as a code block", function() { const {tokens} = grammar.tokenizeLine("~`~"); expect(tokens[0]).toEqual({value: '~', scopes: ['source.gfm']}); expect(tokens[1]).toEqual({value: '`', scopes: ['source.gfm', 'markup.raw.gfm']}); - return expect(tokens[2]).toEqual({value: '~', scopes: ['source.gfm', 'markup.raw.gfm']}); + expect(tokens[2]).toEqual({value: '~', scopes: ['source.gfm', 'markup.raw.gfm']}); }); it("tokenises code-blocks with borders of differing lengths", function() { @@ -271,7 +266,7 @@ describe("GitHub Flavored Markdown grammar", function() { [firstLineTokens, secondLineTokens, thirdLineTokens] = Array.from(grammar.tokenizeLines("~~~~~~~\nfoo bar\n~~~")); expect(firstLineTokens[0]).toEqual({value: '~~~~~~~', scopes: ['source.gfm', 'markup.raw.gfm', 'support.gfm']}); expect(secondLineTokens[0]).toEqual({value: 'foo bar', scopes: ['source.gfm', 'markup.raw.gfm']}); - return expect(thirdLineTokens[0]).toEqual({value: '~~~', scopes: ['source.gfm', 'markup.raw.gfm']}); + expect(thirdLineTokens[0]).toEqual({value: '~~~', scopes: ['source.gfm', 'markup.raw.gfm']}); }); it("tokenizes a ``` code block with trailing whitespace", function() { @@ -280,7 +275,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]}); ({tokens} = grammar.tokenizeLine("``` ", ruleStack)); - return expect(tokens[0]).toEqual({value: "``` ", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); + expect(tokens[0]).toEqual({value: "``` ", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); }); it("tokenizes a ~~~ code block with trailing whitespace", function() { @@ -289,7 +284,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)); expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]}); ({tokens} = grammar.tokenizeLine("~~~ ", ruleStack)); - return expect(tokens[0]).toEqual({value: "~~~ ", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); + expect(tokens[0]).toEqual({value: "~~~ ", scopes: ["source.gfm", "markup.raw.gfm", "support.gfm"]}); }); it("tokenises a ``` code block with an unknown language", function() { @@ -300,7 +295,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[0]).toEqual({value: "-> 'hello'", scopes: ['source.gfm', 'markup.code.other.gfm', 'source.embedded.mylanguage']}); ({tokens} = grammar.tokenizeLine("```", ruleStack)); - return expect(tokens[0]).toEqual({value: '```', scopes: ['source.gfm', 'markup.code.other.gfm', 'support.gfm']}); + expect(tokens[0]).toEqual({value: '```', scopes: ['source.gfm', 'markup.code.other.gfm', 'support.gfm']}); }); it("tokenizes a ``` code block with a known language", function() { @@ -322,7 +317,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("```properties ")); expect(tokens[0]).toEqual({value: "```properties ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"]}); - return expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); }); it("tokenizes a Rmarkdown ``` code block", function() { @@ -336,7 +331,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("```{r eval=TRUE,cache=FALSE}")); expect(tokens[0]).toEqual({value: "```{r eval=TRUE,cache=FALSE}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); - return expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); }); it("tokenizes a Rmarkdown ``` code block with whitespace", function() { @@ -350,7 +345,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("```{r eval = TRUE, cache = FALSE}")); expect(tokens[0]).toEqual({value: "```{r eval = TRUE, cache = FALSE}", scopes: ["source.gfm", "markup.code.r.gfm", "support.gfm"]}); - return expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.r"); }); it("tokenizes a ~~~ code block with a language", function() { @@ -364,7 +359,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("~~~properties ")); expect(tokens[0]).toEqual({value: "~~~properties ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"]}); - return expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); }); it("tokenizes a ``` code block with a language and trailing whitespace", function() { @@ -376,7 +371,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("```js ")); ({tokens} = grammar.tokenizeLine("``` ", ruleStack)); expect(tokens[0]).toEqual({value: "``` ", scopes: ["source.gfm", "markup.code.js.gfm", "support.gfm"]}); - return expect(ruleStack[1].contentScopeName).toBe("source.embedded.js"); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.js"); }); it("tokenizes a ~~~ code block with a language and trailing whitespace", function() { @@ -393,7 +388,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens, ruleStack} = grammar.tokenizeLine("~~~ properties ")); ({tokens} = grammar.tokenizeLine("~~~ ", ruleStack)); expect(tokens[0]).toEqual({value: "~~~ ", scopes: ["source.gfm", "markup.code.git-config.gfm", "support.gfm"]}); - return expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); + expect(ruleStack[1].contentScopeName).toBe("source.embedded.git-config"); }); it("tokenizes inline `code` blocks", function() { @@ -413,7 +408,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens} = grammar.tokenizeLine("``a\\`b``")); expect(tokens[0]).toEqual({value: "``", scopes: ["source.gfm", "markup.raw.gfm"]}); expect(tokens[1]).toEqual({value: "a\\`b", scopes: ["source.gfm", "markup.raw.gfm"]}); - return expect(tokens[2]).toEqual({value: "``", scopes: ["source.gfm", "markup.raw.gfm"]}); + expect(tokens[2]).toEqual({value: "``", scopes: ["source.gfm", "markup.raw.gfm"]}); }); it("tokenizes [links](links)", function() { @@ -424,7 +419,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[4]).toEqual({value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); expect(tokens[5]).toEqual({value: "website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); - return expect(tokens[6]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[6]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); }); it("tokenizes reference [links][links]", function() { @@ -435,7 +430,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[4]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); expect(tokens[5]).toEqual({value: "website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); - return expect(tokens[6]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[6]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); }); it("tokenizes id-less reference [links][]", function() { @@ -445,7 +440,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[2]).toEqual({value: "this link", scopes: ["source.gfm", "link", "entity.gfm"]}); expect(tokens[3]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[4]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); - return expect(tokens[5]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[5]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); }); it("tokenizes [link]: footers", function() { @@ -455,7 +450,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[2]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[3]).toEqual({value: ":", scopes: ["source.gfm", "link", "punctuation.separator.key-value.gfm"]}); expect(tokens[4]).toEqual({value: " ", scopes: ["source.gfm", "link"]}); - return expect(tokens[5]).toEqual({value: "http://website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); + expect(tokens[5]).toEqual({value: "http://website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); }); it("tokenizes [link]: ", function() { @@ -465,7 +460,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[2]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[3]).toEqual({value: ": <", scopes: ["source.gfm", "link"]}); expect(tokens[4]).toEqual({value: "http://website", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); - return expect(tokens[5]).toEqual({value: ">", scopes: ["source.gfm", "link"]}); + expect(tokens[5]).toEqual({value: ">", scopes: ["source.gfm", "link"]}); }); it("tokenizes [![links](links)](links)", function() { @@ -480,7 +475,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[7]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[8]).toEqual({value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); expect(tokens[9]).toEqual({value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); - return expect(tokens[10]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[10]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); }); it("tokenizes [![links](links)][links]", function() { @@ -495,7 +490,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[7]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[8]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); expect(tokens[9]).toEqual({value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); - return expect(tokens[10]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[10]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); }); it("tokenizes [![links][links]](links)", function() { @@ -510,7 +505,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[7]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[8]).toEqual({value: "(", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); expect(tokens[9]).toEqual({value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); - return expect(tokens[10]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[10]).toEqual({value: ")", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); }); it("tokenizes [![links][links]][links]", function() { @@ -525,7 +520,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[7]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); expect(tokens[8]).toEqual({value: "[", scopes: ["source.gfm", "link", "punctuation.definition.begin.gfm"]}); expect(tokens[9]).toEqual({value: "link", scopes: ["source.gfm", "link", "markup.underline.link.gfm"]}); - return expect(tokens[10]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); + expect(tokens[10]).toEqual({value: "]", scopes: ["source.gfm", "link", "punctuation.definition.end.gfm"]}); }); it("tokenizes mentions", function() { @@ -605,7 +600,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens} = grammar.tokenizeLine("@person;")); expect(tokens[0]).toEqual({value: "@", scopes: ["source.gfm", "variable.mention.gfm"]}); expect(tokens[1]).toEqual({value: "person", scopes: ["source.gfm", "string.username.gfm"]}); - return expect(tokens[2]).toEqual({value: ";", scopes: ["source.gfm"]}); + expect(tokens[2]).toEqual({value: ";", scopes: ["source.gfm"]}); }); it("tokenizes issue numbers", function() { @@ -653,7 +648,7 @@ describe("GitHub Flavored Markdown grammar", function() { ({tokens} = grammar.tokenizeLine(" #123's")); expect(tokens[1]).toEqual({value: "#", scopes: ["source.gfm", "variable.issue.tag.gfm"]}); expect(tokens[2]).toEqual({value: "123", scopes: ["source.gfm", "string.issue.number.gfm"]}); - return expect(tokens[3]).toEqual({value: "'s", scopes: ["source.gfm"]}); + expect(tokens[3]).toEqual({value: "'s", scopes: ["source.gfm"]}); }); it("tokenizes unordered lists", function() { @@ -676,7 +671,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); expect(tokens[1]).toEqual({value: "-", scopes: ["source.gfm", "variable.unordered.list.gfm"]}); expect(tokens[2]).toEqual({value: " ", scopes: ["source.gfm"]}); - return expect(tokens[3]).toEqual({value: "Item 3", scopes: ["source.gfm"]}); + expect(tokens[3]).toEqual({value: "Item 3", scopes: ["source.gfm"]}); }); it("tokenizes ordered lists", function() { @@ -699,13 +694,13 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[0]).toEqual({value: " ", scopes: ["source.gfm"]}); expect(tokens[1]).toEqual({value: "111.", scopes: ["source.gfm", "variable.ordered.list.gfm"]}); expect(tokens[2]).toEqual({value: " ", scopes: ["source.gfm"]}); - return expect(tokens[3]).toEqual({value: "Hundred and eleventh item", scopes: ["source.gfm"]}); + expect(tokens[3]).toEqual({value: "Hundred and eleventh item", scopes: ["source.gfm"]}); }); it("tokenizes > quoted text", function() { const {tokens} = grammar.tokenizeLine("> Quotation :+1:"); expect(tokens[0]).toEqual({value: ">", scopes: ["source.gfm", "comment.quote.gfm", "support.quote.gfm"]}); - return expect(tokens[1]).toEqual({value: " Quotation :+1:", scopes: ["source.gfm", "comment.quote.gfm"]}); + expect(tokens[1]).toEqual({value: " Quotation :+1:", scopes: ["source.gfm", "comment.quote.gfm"]}); }); it("tokenizes HTML entities", function() { @@ -730,7 +725,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[12]).toEqual({value: "&", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); expect(tokens[13]).toEqual({value: "#xb3", scopes: ["source.gfm", "constant.character.entity.gfm"]}); - return expect(tokens[14]).toEqual({value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[14]).toEqual({value: ";", scopes: ["source.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); }); it("tokenizes HTML entities in *italic* text", function() { @@ -762,7 +757,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm"]}); expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); - return expect(tokens[12]).toEqual({value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ]}); + expect(tokens[12]).toEqual({value: "_", scopes: [ 'source.gfm', 'markup.italic.gfm', 'punctuation.definition.entity.gfm' ]}); }); it("tokenizes HTML entities in **bold** text", function() { @@ -794,7 +789,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm"]}); expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); - return expect(tokens[12]).toEqual({value: "__", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); + expect(tokens[12]).toEqual({value: "__", scopes: ["source.gfm", "markup.bold.gfm", "punctuation.definition.entity.gfm"]}); }); it("tokenizes HTML entities in ***bold italic*** text", function() { @@ -826,7 +821,7 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.bold.italic.gfm", "constant.character.entity.gfm"]}); - return expect(tokens[12]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); + expect(tokens[12]).toEqual({value: "___", scopes: ["source.gfm", "markup.bold.italic.gfm"]}); }); it("tokenizes HTML entities in strikethrough text", function() { @@ -843,14 +838,14 @@ describe("GitHub Flavored Markdown grammar", function() { expect(tokens[9]).toEqual({value: "&", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); expect(tokens[10]).toEqual({value: "#xb3", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm"]}); expect(tokens[11]).toEqual({value: ";", scopes: ["source.gfm", "markup.strike.gfm", "constant.character.entity.gfm", "punctuation.definition.entity.gfm"]}); - return expect(tokens[12]).toEqual({value: "~~", scopes: ["source.gfm", "markup.strike.gfm"]}); + expect(tokens[12]).toEqual({value: "~~", scopes: ["source.gfm", "markup.strike.gfm"]}); }); it("tokenizes HTML comments", function() { const {tokens} = grammar.tokenizeLine(""); expect(tokens[0]).toEqual({value: "", scopes: ["source.gfm", "comment.block.gfm", "punctuation.definition.comment.gfm"]}); + expect(tokens[2]).toEqual({value: "-->", scopes: ["source.gfm", "comment.block.gfm", "punctuation.definition.comment.gfm"]}); }); it("tokenizes YAML front matter", function() { @@ -863,13 +858,13 @@ front: matter expect(firstLineTokens[0]).toEqual({value: "---", scopes: ["source.gfm", "front-matter.yaml.gfm", "comment.hr.gfm"]}); expect(secondLineTokens[0]).toEqual({value: "front: matter", scopes: ["source.gfm", "front-matter.yaml.gfm"]}); - return expect(thirdLineTokens[0]).toEqual({value: "---", scopes: ["source.gfm", "front-matter.yaml.gfm", "comment.hr.gfm"]}); + expect(thirdLineTokens[0]).toEqual({value: "---", scopes: ["source.gfm", "front-matter.yaml.gfm", "comment.hr.gfm"]}); }); it("tokenizes linebreaks", function() { const {tokens} = grammar.tokenizeLine("line "); expect(tokens[0]).toEqual({value: "line", scopes: ["source.gfm"]}); - return expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "linebreak.gfm"]}); + expect(tokens[1]).toEqual({value: " ", scopes: ["source.gfm", "linebreak.gfm"]}); }); it("tokenizes tables", function() { @@ -920,10 +915,10 @@ front: matter expect(headingTokens[0]).toEqual({value: "#", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.marker.gfm"]}); expect(headingTokens[1]).toEqual({value: " ", scopes: ["source.gfm", "markup.heading.heading-1.gfm", "markup.heading.space.gfm"]}); - return expect(headingTokens[2]).toEqual({value: "Heading", scopes: ["source.gfm", "markup.heading.heading-1.gfm"]}); + expect(headingTokens[2]).toEqual({value: "Heading", scopes: ["source.gfm", "markup.heading.heading-1.gfm"]}); }); - return it("tokenizes criticmarkup", function() { + it("tokenizes criticmarkup", function() { const [addToken, delToken, hlToken, subToken] = Array.from(grammar.tokenizeLines(`\ Add{++ some text++} Delete{-- some text--} @@ -955,6 +950,6 @@ Replace {~~this~>by that~~}\ expect(subToken[2]).toEqual({value: "this", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution"]}); expect(subToken[3]).toEqual({value: "~>", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.operator"]}); expect(subToken[4]).toEqual({value: "by that", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution"]}); - return expect(subToken[5]).toEqual({value: "~~}", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.marker"]}); + expect(subToken[5]).toEqual({value: "~~}", scopes: ["source.gfm", "markup.changed.critic.gfm.substitution", "punctuation.definition.changed.critic.gfm.substitution.marker"]}); }); }); From 50aa999d144774c9637f5e2534abc467e2592786 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 18:13:17 -0700 Subject: [PATCH 09/18] Decaf `language-git` --- packages/language-git/spec/git-spec.coffee | 196 --------------------- packages/language-git/spec/git-spec.js | 38 ++-- 2 files changed, 17 insertions(+), 217 deletions(-) delete mode 100644 packages/language-git/spec/git-spec.coffee diff --git a/packages/language-git/spec/git-spec.coffee b/packages/language-git/spec/git-spec.coffee deleted file mode 100644 index a239ec5063..0000000000 --- a/packages/language-git/spec/git-spec.coffee +++ /dev/null @@ -1,196 +0,0 @@ -describe "Git grammars", -> - grammar = null - - beforeEach -> - waitsForPromise -> - atom.packages.activatePackage("language-git") - - describe "Git configs", -> - beforeEach -> - grammar = atom.grammars.grammarForScopeName("source.git-config") - - it "parses the Git config grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe "source.git-config" - - describe "Git commit messages", -> - scopeNormal = ['text.git-commit', 'meta.scope.message.git-commit'] - - scopeLeadingLowercase = - ['text.git-commit', 'meta.scope.message.git-commit', 'invalid.illegal.first-char-should-be-uppercase.git-commit'] - - scopeTrailingPeriod = - ['text.git-commit', 'meta.scope.message.git-commit', 'invalid.illegal.subject-no-trailing-period.git-commit'] - - scopeLineOver50 = ['text.git-commit', 'meta.scope.message.git-commit', 'invalid.deprecated.line-too-long.git-commit'] - - scopeLineOver72 = ['text.git-commit', 'meta.scope.message.git-commit', 'invalid.illegal.line-too-long.git-commit'] - - beforeEach -> - grammar = atom.grammars.grammarForScopeName("text.git-commit") - - it "parses the Git commit message grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe "text.git-commit" - - it "highlights subject lines of less than 50 chars correctly", -> - {tokens} = grammar.tokenizeLine("123456789012345678901234567890", null, true) - expect(tokens[0]).toEqual value: '123456789012345678901234567890', scopes: scopeNormal - - {tokens} = grammar.tokenizeLine("a23456789012345678901234567890", null, true) - expect(tokens[0]).toEqual value: 'a', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '23456789012345678901234567890', scopes: scopeNormal - - {tokens} = grammar.tokenizeLine("12345678901234567890123456789.", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789', scopes: scopeNormal - expect(tokens[1]).toEqual value: '.', scopes: scopeTrailingPeriod - - {tokens} = grammar.tokenizeLine("b2345678901234567890123456789.", null, true) - expect(tokens[0]).toEqual value: 'b', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789', scopes: scopeNormal - expect(tokens[2]).toEqual value: '.', scopes: scopeTrailingPeriod - - it "highlights subject lines of 50 chars correctly", -> - {tokens} = grammar.tokenizeLine("12345678901234567890123456789012345678901234567890", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - - {tokens} = grammar.tokenizeLine("c2345678901234567890123456789012345678901234567890", null, true) - expect(tokens[0]).toEqual value: 'c', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - - {tokens} = grammar.tokenizeLine("1234567890123456789012345678901234567890123456789.", null, true) - expect(tokens[0]).toEqual value: '1234567890123456789012345678901234567890123456789', scopes: scopeNormal - expect(tokens[1]).toEqual value: '.', scopes: scopeTrailingPeriod - - {tokens} = grammar.tokenizeLine("d234567890123456789012345678901234567890123456789.", null, true) - expect(tokens[0]).toEqual value: 'd', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '234567890123456789012345678901234567890123456789', scopes: scopeNormal - expect(tokens[2]).toEqual value: '.', scopes: scopeTrailingPeriod - - it "highlights subject lines of 51 chars correctly", -> - {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[1]).toEqual value: '1', scopes: scopeLineOver50 - - {tokens} = grammar.tokenizeLine("e23456789012345678901234567890123456789012345678901", null, true) - expect(tokens[0]).toEqual value: 'e', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[2]).toEqual value: '1', scopes: scopeLineOver50 - - {tokens} = grammar.tokenizeLine("12345678901234567890123456789012345678901234567890.", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[1]).toEqual value: '.', scopes: scopeTrailingPeriod - - {tokens} = grammar.tokenizeLine("f2345678901234567890123456789012345678901234567890.", null, true) - expect(tokens[0]).toEqual value: 'f', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[2]).toEqual value: '.', scopes: scopeTrailingPeriod - - it "highlights subject lines of 72 chars correctly", -> - {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[1]).toEqual value: '123456789012345678901', scopes: scopeLineOver50 - expect(tokens[2]).toEqual value: '2', scopes: scopeLineOver50 - - {tokens} = grammar.tokenizeLine("g23456789012345678901234567890123456789012345678901234567890123456789012", null, true) - expect(tokens[0]).toEqual value: 'g', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[2]).toEqual value: '123456789012345678901', scopes: scopeLineOver50 - expect(tokens[3]).toEqual value: '2', scopes: scopeLineOver50 - - {tokens} = grammar.tokenizeLine("12345678901234567890123456789012345678901234567890123456789012345678901.", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[1]).toEqual value: '123456789012345678901', scopes: scopeLineOver50 - expect(tokens[2]).toEqual value: '.', scopes: scopeTrailingPeriod - - {tokens} = grammar.tokenizeLine("h2345678901234567890123456789012345678901234567890123456789012345678901.", null, true) - expect(tokens[0]).toEqual value: 'h', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[2]).toEqual value: '123456789012345678901', scopes: scopeLineOver50 - expect(tokens[3]).toEqual value: '.', scopes: scopeTrailingPeriod - - it "highlights subject lines of 73 chars correctly", -> - {tokens} = grammar.tokenizeLine("1234567890123456789012345678901234567890123456789012345678901234567890123", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[1]).toEqual value: '1234567890123456789012', scopes: scopeLineOver50 - expect(tokens[2]).toEqual value: '3', scopes: scopeLineOver72 - - {tokens} = grammar.tokenizeLine("i234567890123456789012345678901234567890123456789012345678901234567890123", null, true) - expect(tokens[0]).toEqual value: 'i', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[2]).toEqual value: '1234567890123456789012', scopes: scopeLineOver50 - expect(tokens[3]).toEqual value: '3', scopes: scopeLineOver72 - - {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012.", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[1]).toEqual value: '1234567890123456789012', scopes: scopeLineOver50 - expect(tokens[2]).toEqual value: '.', scopes: scopeTrailingPeriod - - {tokens} = grammar.tokenizeLine("j23456789012345678901234567890123456789012345678901234567890123456789012.", null, true) - expect(tokens[0]).toEqual value: 'j', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[2]).toEqual value: '1234567890123456789012', scopes: scopeLineOver50 - expect(tokens[3]).toEqual value: '.', scopes: scopeTrailingPeriod - - it "highlights subject lines of over 73 chars correctly", -> - {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012345678", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[1]).toEqual value: '1234567890123456789012', scopes: scopeLineOver50 - expect(tokens[2]).toEqual value: '345678', scopes: scopeLineOver72 - - {tokens} = grammar.tokenizeLine("k23456789012345678901234567890123456789012345678901234567890123456789012345678", null, true) - expect(tokens[0]).toEqual value: 'k', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[2]).toEqual value: '1234567890123456789012', scopes: scopeLineOver50 - expect(tokens[3]).toEqual value: '345678', scopes: scopeLineOver72 - - {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012345678.", null, true) - expect(tokens[0]).toEqual value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[1]).toEqual value: '1234567890123456789012', scopes: scopeLineOver50 - expect(tokens[2]).toEqual value: '345678', scopes: scopeLineOver72 - expect(tokens[3]).toEqual value: '.', scopes: scopeTrailingPeriod - - {tokens} = grammar.tokenizeLine("m23456789012345678901234567890123456789012345678901234567890123456789012345678.", null, true) - expect(tokens[0]).toEqual value: 'm', scopes: scopeLeadingLowercase - expect(tokens[1]).toEqual value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal - expect(tokens[2]).toEqual value: '1234567890123456789012', scopes: scopeLineOver50 - expect(tokens[3]).toEqual value: '345678', scopes: scopeLineOver72 - expect(tokens[4]).toEqual value: '.', scopes: scopeTrailingPeriod - - describe "Git rebases", -> - beforeEach -> - grammar = atom.grammars.grammarForScopeName("text.git-rebase") - - it "parses the Git rebase message grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe "text.git-rebase" - - for cmd in ["pick", "p", "reword", "r", "edit", "e", "squash", "s", "fixup", "f", "drop", "d"] - it "parses the #{cmd} command", -> - {tokens} = grammar.tokenizeLine "#{cmd} c0ffeee This is commit message" - - expect(tokens[0]).toEqual value: cmd, scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "support.function.git-rebase"] - expect(tokens[1]).toEqual value: " ", scopes: ["text.git-rebase", "meta.commit-command.git-rebase"] - expect(tokens[2]).toEqual value: "c0ffeee", scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "constant.sha.git-rebase"] - expect(tokens[3]).toEqual value: " ", scopes: ["text.git-rebase", "meta.commit-command.git-rebase"] - expect(tokens[4]).toEqual value: "This is commit message", scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "meta.commit-message.git-rebase"] - - it "parses the exec command", -> - {tokens} = grammar.tokenizeLine "exec" - - expect(tokens[0]).toEqual value: "exec", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"] - - {tokens} = grammar.tokenizeLine "x" - - expect(tokens[0]).toEqual value: "x", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"] - - it "includes language-shellscript highlighting when using the exec command", -> - waitsForPromise -> - atom.packages.activatePackage("language-shellscript") - - runs -> - {tokens} = grammar.tokenizeLine "exec echo 'Hello World'" - - expect(tokens[0]).toEqual value: "exec", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"] - expect(tokens[1]).toEqual value: " ", scopes: ["text.git-rebase", "meta.exec-command.git-rebase"] - expect(tokens[2]).toEqual value: "echo", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.builtin.shell"] diff --git a/packages/language-git/spec/git-spec.js b/packages/language-git/spec/git-spec.js index ed04464d0b..837bd67e9f 100644 --- a/packages/language-git/spec/git-spec.js +++ b/packages/language-git/spec/git-spec.js @@ -1,8 +1,4 @@ -/* - * decaffeinate suggestions: - * DS102: Remove unnecessary code created because of implicit returns - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe("Git grammars", function() { let grammar = null; @@ -11,9 +7,9 @@ describe("Git grammars", function() { describe("Git configs", function() { beforeEach(() => grammar = atom.grammars.grammarForScopeName("source.git-config")); - return it("parses the Git config grammar", function() { + it("parses the Git config grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe("source.git-config"); + expect(grammar.scopeName).toBe("source.git-config"); }); }); @@ -34,7 +30,7 @@ describe("Git grammars", function() { it("parses the Git commit message grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe("text.git-commit"); + expect(grammar.scopeName).toBe("text.git-commit"); }); it("highlights subject lines of less than 50 chars correctly", function() { @@ -52,7 +48,7 @@ describe("Git grammars", function() { ({tokens} = grammar.tokenizeLine("b2345678901234567890123456789.", null, true)); expect(tokens[0]).toEqual({value: 'b', scopes: scopeLeadingLowercase}); expect(tokens[1]).toEqual({value: '2345678901234567890123456789', scopes: scopeNormal}); - return expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); }); it("highlights subject lines of 50 chars correctly", function() { @@ -70,7 +66,7 @@ describe("Git grammars", function() { ({tokens} = grammar.tokenizeLine("d234567890123456789012345678901234567890123456789.", null, true)); expect(tokens[0]).toEqual({value: 'd', scopes: scopeLeadingLowercase}); expect(tokens[1]).toEqual({value: '234567890123456789012345678901234567890123456789', scopes: scopeNormal}); - return expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); }); it("highlights subject lines of 51 chars correctly", function() { @@ -90,7 +86,7 @@ describe("Git grammars", function() { ({tokens} = grammar.tokenizeLine("f2345678901234567890123456789012345678901234567890.", null, true)); expect(tokens[0]).toEqual({value: 'f', scopes: scopeLeadingLowercase}); expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); - return expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + expect(tokens[2]).toEqual({value: '.', scopes: scopeTrailingPeriod}); }); it("highlights subject lines of 72 chars correctly", function() { @@ -114,7 +110,7 @@ describe("Git grammars", function() { expect(tokens[0]).toEqual({value: 'h', scopes: scopeLeadingLowercase}); expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); expect(tokens[2]).toEqual({value: '123456789012345678901', scopes: scopeLineOver50}); - return expect(tokens[3]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + expect(tokens[3]).toEqual({value: '.', scopes: scopeTrailingPeriod}); }); it("highlights subject lines of 73 chars correctly", function() { @@ -138,10 +134,10 @@ describe("Git grammars", function() { expect(tokens[0]).toEqual({value: 'j', scopes: scopeLeadingLowercase}); expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); expect(tokens[2]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); - return expect(tokens[3]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + expect(tokens[3]).toEqual({value: '.', scopes: scopeTrailingPeriod}); }); - return it("highlights subject lines of over 73 chars correctly", function() { + it("highlights subject lines of over 73 chars correctly", function() { let {tokens} = grammar.tokenizeLine("123456789012345678901234567890123456789012345678901234567890123456789012345678", null, true); expect(tokens[0]).toEqual({value: '12345678901234567890123456789012345678901234567890', scopes: scopeNormal}); expect(tokens[1]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); @@ -164,16 +160,16 @@ describe("Git grammars", function() { expect(tokens[1]).toEqual({value: '2345678901234567890123456789012345678901234567890', scopes: scopeNormal}); expect(tokens[2]).toEqual({value: '1234567890123456789012', scopes: scopeLineOver50}); expect(tokens[3]).toEqual({value: '345678', scopes: scopeLineOver72}); - return expect(tokens[4]).toEqual({value: '.', scopes: scopeTrailingPeriod}); + expect(tokens[4]).toEqual({value: '.', scopes: scopeTrailingPeriod}); }); }); - return describe("Git rebases", function() { + describe("Git rebases", function() { beforeEach(() => grammar = atom.grammars.grammarForScopeName("text.git-rebase")); it("parses the Git rebase message grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe("text.git-rebase"); + expect(grammar.scopeName).toBe("text.git-rebase"); }); for (var cmd of ["pick", "p", "reword", "r", "edit", "e", "squash", "s", "fixup", "f", "drop", "d"]) { @@ -184,7 +180,7 @@ describe("Git grammars", function() { expect(tokens[1]).toEqual({value: " ", scopes: ["text.git-rebase", "meta.commit-command.git-rebase"]}); expect(tokens[2]).toEqual({value: "c0ffeee", scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "constant.sha.git-rebase"]}); expect(tokens[3]).toEqual({value: " ", scopes: ["text.git-rebase", "meta.commit-command.git-rebase"]}); - return expect(tokens[4]).toEqual({value: "This is commit message", scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "meta.commit-message.git-rebase"]}); + expect(tokens[4]).toEqual({value: "This is commit message", scopes: ["text.git-rebase", "meta.commit-command.git-rebase", "meta.commit-message.git-rebase"]}); }); } @@ -195,10 +191,10 @@ describe("Git grammars", function() { ({tokens} = grammar.tokenizeLine("x")); - return expect(tokens[0]).toEqual({value: "x", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"]}); + expect(tokens[0]).toEqual({value: "x", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"]}); }); - return it("includes language-shellscript highlighting when using the exec command", function() { + it("includes language-shellscript highlighting when using the exec command", function() { waitsForPromise(() => atom.packages.activatePackage("language-shellscript")); return runs(function() { @@ -206,7 +202,7 @@ describe("Git grammars", function() { expect(tokens[0]).toEqual({value: "exec", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.git-rebase"]}); expect(tokens[1]).toEqual({value: " ", scopes: ["text.git-rebase", "meta.exec-command.git-rebase"]}); - return expect(tokens[2]).toEqual({value: "echo", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.builtin.shell"]});}); + expect(tokens[2]).toEqual({value: "echo", scopes: ["text.git-rebase", "meta.exec-command.git-rebase", "support.function.builtin.shell"]});}); }); }); }); From 7d7433e39913e7ab4a62ec2f9772743a3d441ccd Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 8 Jul 2023 18:15:07 -0700 Subject: [PATCH 10/18] Decaf `langauge-go` --- packages/language-go/spec/go-spec.coffee | 977 ------------------ packages/language-go/spec/go-spec.js | 100 +- .../language-go/spec/language-go-spec.coffee | 63 -- packages/language-go/spec/language-go-spec.js | 17 +- 4 files changed, 53 insertions(+), 1104 deletions(-) delete mode 100644 packages/language-go/spec/go-spec.coffee delete mode 100644 packages/language-go/spec/language-go-spec.coffee diff --git a/packages/language-go/spec/go-spec.coffee b/packages/language-go/spec/go-spec.coffee deleted file mode 100644 index 2d7179617a..0000000000 --- a/packages/language-go/spec/go-spec.coffee +++ /dev/null @@ -1,977 +0,0 @@ -describe 'Go grammar', -> - grammar = null - - beforeEach -> - atom.config.set 'core.useTreeSitterParsers', false - - waitsForPromise -> - atom.packages.activatePackage('language-go') - - runs -> - grammar = atom.grammars.grammarForScopeName('source.go') - - it 'parses the grammar', -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe 'source.go' - - it 'tokenizes comments', -> - {tokens} = grammar.tokenizeLine('// I am a comment') - expect(tokens[0].value).toEqual '//' - expect(tokens[0].scopes).toEqual ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go'] - expect(tokens[1].value).toEqual ' I am a comment' - expect(tokens[1].scopes).toEqual ['source.go', 'comment.line.double-slash.go'] - - tokens = grammar.tokenizeLines('/*\nI am a comment\n*/') - expect(tokens[0][0].value).toEqual '/*' - expect(tokens[0][0].scopes).toEqual ['source.go', 'comment.block.go', 'punctuation.definition.comment.go'] - expect(tokens[1][0].value).toEqual 'I am a comment' - expect(tokens[1][0].scopes).toEqual ['source.go', 'comment.block.go'] - expect(tokens[2][0].value).toEqual '*/' - expect(tokens[2][0].scopes).toEqual ['source.go', 'comment.block.go', 'punctuation.definition.comment.go'] - - it 'tokenizes comments in imports', -> - lines = grammar.tokenizeLines ''' - import ( - //"fmt" - "os" // comment - // comment! - ) - ''' - expect(lines[1][1]).toEqual value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go'] - expect(lines[2][5]).toEqual value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go'] - expect(lines[3][1]).toEqual value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go'] - - it 'tokenizes strings', -> - delims = - 'string.quoted.double.go': '"' - 'string.quoted.raw.go': '`' - - for scope, delim of delims - {tokens} = grammar.tokenizeLine(delim + 'I am a string' + delim) - expect(tokens[0].value).toEqual delim - expect(tokens[0].scopes).toEqual ['source.go', scope, 'punctuation.definition.string.begin.go'] - expect(tokens[1].value).toEqual 'I am a string' - expect(tokens[1].scopes).toEqual ['source.go', scope] - expect(tokens[2].value).toEqual delim - expect(tokens[2].scopes).toEqual ['source.go', scope, 'punctuation.definition.string.end.go'] - - it 'tokenizes placeholders in strings', -> - # Taken from go/src/pkg/fmt/fmt_test.go - verbs = [ - '%# x', '%-5s', '%5s', '%05s', '%.5s', '%10.1q', '%10v', '%-10v', '%.0d' - '%.d', '%+07.2f', '%0100d', '%0.100f', '%#064x', '%+.3F', '%-#20.8x', - '%[1]d', '%[2]*[1]d', '%[3]*.[2]*[1]f', '%[3]*.[2]f', '%3.[2]d', '%.[2]d' - '%-+[1]x', '%d', '%-d', '%+d', '%#d', '% d', '%0d', '%1.2d', '%-1.2d' - '%+1.2d', '%-+1.2d', '%*d', '%.*d', '%*.*d', '%0*d', '%-*d' - ] - - for verb in verbs - {tokens} = grammar.tokenizeLine('"' + verb + '"') - expect(tokens[0].value).toEqual '"', - expect(tokens[0].scopes).toEqual ['source.go', 'string.quoted.double.go', 'punctuation.definition.string.begin.go'] - expect(tokens[1].value).toEqual verb - expect(tokens[1].scopes).toEqual ['source.go', 'string.quoted.double.go', 'constant.other.placeholder.go'] - expect(tokens[2].value).toEqual '"', - expect(tokens[2].scopes).toEqual ['source.go', 'string.quoted.double.go', 'punctuation.definition.string.end.go'] - - it 'tokenizes character escapes in strings', -> - escapes = [ - '\\a', '\\b', '\\f', '\\n', '\\r', '\\t', '\\v', '\\\\' - '\\000', '\\007', '\\377', '\\x07', '\\xff', '\\u12e4', '\\U00101234' - ] - - for escape in escapes - {tokens} = grammar.tokenizeLine('"' + escape + '"') - expect(tokens[1].value).toEqual escape - expect(tokens[1].scopes).toEqual ['source.go', 'string.quoted.double.go', 'constant.character.escape.go'] - - {tokens} = grammar.tokenizeLine('"\\""') - expect(tokens[1].value).toEqual '\\"' - expect(tokens[1].scopes).toEqual ['source.go', 'string.quoted.double.go', 'constant.character.escape.go'] - - it 'tokenizes placeholders in raw strings', -> - # Taken from go/src/pkg/fmt/fmt_test.go - verbs = [ - '%# x', '%-5s', '%5s', '%05s', '%.5s', '%10.1q', '%10v', '%-10v', '%.0d' - '%.d', '%+07.2f', '%0100d', '%0.100f', '%#064x', '%+.3F', '%-#20.8x', - '%[1]d', '%[2]*[1]d', '%[3]*.[2]*[1]f', '%[3]*.[2]f', '%3.[2]d', '%.[2]d' - '%-+[1]x', '%d', '%-d', '%+d', '%#d', '% d', '%0d', '%1.2d', '%-1.2d' - '%+1.2d', '%-+1.2d', '%*d', '%.*d', '%*.*d', '%0*d', '%-*d' - ] - - for verb in verbs - {tokens} = grammar.tokenizeLine('`' + verb + '`') - expect(tokens[0].value).toEqual '`', - expect(tokens[0].scopes).toEqual ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.begin.go'] - expect(tokens[1].value).toEqual verb - expect(tokens[1].scopes).toEqual ['source.go', 'string.quoted.raw.go', 'constant.other.placeholder.go'] - expect(tokens[2].value).toEqual '`', - expect(tokens[2].scopes).toEqual ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.end.go'] - - it 'tokenizes runes', -> - runes = [ - 'u', 'X', '$', ':', '(', '.', '2', '=', '!', '@', - '\\a', '\\b', '\\f', '\\n', '\\r', '\\t', '\\v', '\\\\', "\\'", '\\"', - '\\000', '\\007', '\\377', '\\x07', '\\xff', '\\u12e4', '\\U00101234' - ] - - for rune in runes - {tokens} = grammar.tokenizeLine("'#{rune}'") - expect(tokens[0]).toEqual value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go'] - expect(tokens[1]).toEqual value: rune, scopes: ['source.go', 'string.quoted.rune.go', 'constant.other.rune.go'] - expect(tokens[2]).toEqual value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go'] - - it 'tokenizes invalid runes and single quoted strings', -> - {tokens} = grammar.tokenizeLine("'\\c'") - expect(tokens[0]).toEqual value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go'] - expect(tokens[1]).toEqual value: '\\c', scopes: ['source.go', 'string.quoted.rune.go', 'invalid.illegal.unknown-rune.go'] - expect(tokens[2]).toEqual value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go'] - - {tokens} = grammar.tokenizeLine("'ab'") - expect(tokens[0]).toEqual value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go'] - expect(tokens[1]).toEqual value: 'ab', scopes: ['source.go', 'string.quoted.rune.go', 'invalid.illegal.unknown-rune.go'] - expect(tokens[2]).toEqual value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go'] - - {tokens} = grammar.tokenizeLine("'some single quote string'") - expect(tokens[0]).toEqual value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go'] - expect(tokens[1]).toEqual value: 'some single quote string', scopes: ['source.go', 'string.quoted.rune.go', 'invalid.illegal.unknown-rune.go'] - expect(tokens[2]).toEqual value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go'] - - it 'tokenizes invalid whitespace around chan annotations', -> - invalid_send = - 'chan <- sendonly': ' ' - - invalid_receive = - '<- chan recvonly': ' ' - - for expr, invalid of invalid_send - {tokens} = grammar.tokenizeLine(expr) - expect(tokens[1].value).toEqual invalid - expect(tokens[1].scopes).toEqual ['source.go', 'invalid.illegal.send-channel.go'] - - for expr, invalid of invalid_receive - {tokens} = grammar.tokenizeLine(expr) - expect(tokens[1].value).toEqual invalid - expect(tokens[1].scopes).toEqual ['source.go', 'invalid.illegal.receive-channel.go'] - - it 'tokenizes keywords', -> - keywordLists = - 'keyword.control.go': ['break', 'case', 'continue', 'default', 'defer', 'else', 'fallthrough', 'for', 'go', 'goto', 'if', 'range', 'return', 'select', 'switch'] - 'keyword.channel.go': ['chan'] - 'keyword.const.go': ['const'] - 'keyword.function.go': ['func'] - 'keyword.interface.go': ['interface'] - 'keyword.import.go': ['import'] - 'keyword.map.go': ['map'] - 'keyword.package.go': ['package'] - 'keyword.struct.go': ['struct'] - 'keyword.type.go': ['type'] - 'keyword.var.go': ['var'] - - for scope, list of keywordLists - for keyword in list - {tokens} = grammar.tokenizeLine keyword - expect(tokens[0].value).toEqual keyword - expect(tokens[0].scopes).toEqual ['source.go', scope] - - it 'tokenizes storage types', -> - storageTypes = - 'storage.type.boolean.go': ['bool'] - 'storage.type.byte.go': ['byte'] - 'storage.type.error.go': ['error'] - 'storage.type.numeric.go': ['int', 'int8', 'int16', 'int32', 'int64', 'uint', 'uint8', 'uint16', 'uint32', 'uint64', 'float32', 'float64', 'complex64', 'complex128'] - 'storage.type.rune.go': ['rune'] - 'storage.type.string.go': ['string'] - 'storage.type.uintptr.go': ['uintptr'] - - for scope, types of storageTypes - for type in types - {tokens} = grammar.tokenizeLine type - expect(tokens[0].value).toEqual type - expect(tokens[0].scopes).toEqual ['source.go', scope] - - it 'tokenizes func regardless of the context', -> - funcKeyword = ['func f()', 'func (x) f()', 'func(x) f()', 'func'] - for line in funcKeyword - {tokens} = grammar.tokenizeLine line - expect(tokens[0].value).toEqual 'func' - expect(tokens[0].scopes).toEqual ['source.go', 'keyword.function.go'] - - funcType = [ - { - 'line': 'var f1 func(' - 'tokenPos': 4 - } - { - 'line': 'f2 :=func()' - 'tokenPos': 3 - } - { - 'line': '\tfunc(' - 'tokenPos': 1 - } - { - 'line': 'type HandlerFunc func(' - 'tokenPos': 4 - } - ] - for t in funcType - {tokens} = grammar.tokenizeLine t.line - relevantToken = tokens[t.tokenPos] - expect(relevantToken.value).toEqual 'func' - expect(relevantToken.scopes).toEqual ['source.go', 'keyword.function.go'] - - next = tokens[t.tokenPos + 1] - expect(next.value).toEqual '(' - expect(next.scopes).toEqual ['source.go', 'punctuation.definition.begin.bracket.round.go'] - - it 'only tokenizes func when it is an exact match', -> - tests = ['myfunc', 'funcMap'] - for test in tests - {tokens} = grammar.tokenizeLine test - expect(tokens[0].value).not.toEqual 'func' - expect(tokens[0].scopes).not.toEqual ['source.go', 'keyword.function.go'] - - it 'tokenizes func names in their declarations', -> - tests = [ - { - 'line': 'func f()' - 'tokenPos': 2 - } - { - 'line': 'func (T) f()' - 'tokenPos': 6 - } - { - 'line': 'func (t T) f()' - 'tokenPos': 6 - } - { - 'line': 'func (t *T) f()' - 'tokenPos': 8 - } - ] - - for t in tests - {tokens} = grammar.tokenizeLine t.line - expect(tokens[0].value).toEqual 'func' - expect(tokens[0].scopes).toEqual ['source.go', 'keyword.function.go'] - - relevantToken = tokens[t.tokenPos] - expect(relevantToken).toBeDefined() - expect(relevantToken.value).toEqual 'f' - expect(relevantToken.scopes).toEqual ['source.go', 'entity.name.function.go'] - - next = tokens[t.tokenPos + 1] - expect(next.value).toEqual '(' - expect(next.scopes).toEqual ['source.go', 'punctuation.definition.begin.bracket.round.go'] - - it 'tokenizes operators method declarations', -> - tests = [ - { - 'line': 'func (t *T) f()' - 'tokenPos': 4 - } - ] - - for t in tests - {tokens} = grammar.tokenizeLine t.line - expect(tokens[0].value).toEqual 'func' - expect(tokens[0].scopes).toEqual ['source.go', 'keyword.function.go'] - - relevantToken = tokens[t.tokenPos] - expect(relevantToken.value).toEqual '*' - expect(relevantToken.scopes).toEqual ['source.go', 'keyword.operator.address.go'] - - it 'tokenizes numerics', -> - numbers = - 'constant.numeric.integer.go': ['42', '0600', '0xBadFace', '170141183460469231731687303715884105727', '1E6', '0i', '011i', '1E6i'] - 'constant.numeric.floating-point.go': [ - '0.', '72.40', '072.40', '2.71828', '1.e+0', '6.67428e-11', '.25', '.12345E+5', - '0.i', '2.71828i', '1.e+0i', '6.67428e-11i', '.25i', '.12345E+5i' - ] - - for scope, nums of numbers - for num in nums - {tokens} = grammar.tokenizeLine num - expect(tokens[0].value).toEqual num - expect(tokens[0].scopes).toEqual ['source.go', scope] - - invalidOctals = ['08', '039', '0995'] - for num in invalidOctals - {tokens} = grammar.tokenizeLine num - expect(tokens[0].value).toEqual num - expect(tokens[0].scopes).toEqual ['source.go', 'invalid.illegal.numeric.go'] - - it 'tokenizes language constants', -> - constants = ['true', 'false', 'nil', 'iota'] - for constant in constants - {tokens} = grammar.tokenizeLine constant - expect(tokens[0].value).toEqual constant - expect(tokens[0].scopes).toEqual ['source.go', 'constant.language.go'] - - it 'tokenizes built-in functions', -> - funcs = [ - 'append(x)', 'cap(x)', 'close(x)', 'complex(x)', 'copy(x)', 'delete(x)', 'imag(x)', 'len(x)', 'make(x)', 'new(x)', - 'panic(x)', 'print(x)', 'println(x)', 'real(x)', 'recover(x)' - ] - funcVals = ['append', 'cap', 'close', 'complex', 'copy', 'delete', 'imag', 'len', 'make', 'new', 'panic', 'print', 'println', 'real', 'recover'] - - for func in funcs - funcVal = funcVals[funcs.indexOf(func)] - {tokens} = grammar.tokenizeLine func - expect(tokens[0].value).toEqual funcVal - expect(tokens[0].scopes).toEqual ['source.go', 'support.function.builtin.go'] - - it 'tokenizes operators', -> - binaryOpers = - 'keyword.operator.arithmetic.go': ['+', '-', '*', '/', '%'] - 'keyword.operator.arithmetic.bitwise.go': ['&', '|', '^', '&^', '<<', '>>'] - 'keyword.operator.assignment.go': ['=', '+=', '-=', '|=', '^=', '*=', '/=', ':=', '%=', '<<=', '>>=', '&=', '&^='] - 'keyword.operator.channel.go': ['<-'] - 'keyword.operator.comparison.go': ['==', '!=', '<', '<=', '>', '>='] - 'keyword.operator.decrement.go': ['--'] - 'keyword.operator.ellipsis.go': ['...'] - 'keyword.operator.increment.go': ['++'] - 'keyword.operator.logical.go': ['&&', '||'] - - unaryOpers = - 'keyword.operator.address.go': ['*var', '&var'] - 'keyword.operator.arithmetic.go': ['+var', '-var'] - 'keyword.operator.arithmetic.bitwise.go': ['^var'] - 'keyword.operator.logical.go': ['!var'] - - for scope, ops of binaryOpers - for op in ops - {tokens} = grammar.tokenizeLine op - expect(tokens[0].value).toEqual op - expect(tokens[0].scopes).toEqual ['source.go', scope] - - for scope, ops of unaryOpers - for op in ops - {tokens} = grammar.tokenizeLine op - expect(tokens[0].value).toEqual op[0] - expect(tokens[0].scopes).toEqual ['source.go', scope] - - it 'does not treat values/variables attached to comparion operators as extensions of the operator', -> - {tokens} = grammar.tokenizeLine '2<3.0 && 12>bar' - expect(tokens[0]).toEqual value: '2', scopes: ['source.go', 'constant.numeric.integer.go'] - expect(tokens[1]).toEqual value: '<', scopes: ['source.go', 'keyword.operator.comparison.go'] - expect(tokens[2]).toEqual value: '3.0', scopes: ['source.go', 'constant.numeric.floating-point.go'] - expect(tokens[6]).toEqual value: '12', scopes: ['source.go', 'constant.numeric.integer.go'] - expect(tokens[7]).toEqual value: '>', scopes: ['source.go', 'keyword.operator.comparison.go'] - expect(tokens[8]).toEqual value: 'bar', scopes: ['source.go'] - - it 'tokenizes punctuation brackets', -> - {tokens} = grammar.tokenizeLine '{([])}' - expect(tokens[0]).toEqual value: '{', scopes: ['source.go', 'punctuation.definition.begin.bracket.curly.go'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.go', 'punctuation.definition.begin.bracket.round.go'] - expect(tokens[2]).toEqual value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - expect(tokens[3]).toEqual value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - expect(tokens[4]).toEqual value: ')', scopes: ['source.go', 'punctuation.definition.end.bracket.round.go'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.go', 'punctuation.definition.end.bracket.curly.go'] - - it 'tokenizes punctuation delimiters', -> - delims = - 'punctuation.other.comma.go': ',' - 'punctuation.other.period.go': '.' - 'punctuation.other.colon.go': ':' - - for scope, delim of delims - {tokens} = grammar.tokenizeLine delim - expect(tokens[0].value).toEqual delim - expect(tokens[0].scopes).toEqual ['source.go', scope] - - it 'tokenizes func names in calls to them', -> - tests = [ - { - 'line': 'a.b()' - 'name': 'b' - 'tokenPos': 2 - 'isFunc': true - } - { - 'line': 'pkg.Func1(' - 'name': 'Func1' - 'tokenPos': 2 - 'isFunc': true - } - { - 'line': 'pkg.Func1().Func2(' - 'name': 'Func2' - 'tokenPos': 6 - 'isFunc': true - } - { - 'line': 'pkg.var' - 'name': 'var' - 'tokenPos': 2 - 'isFunc': false - } - { - 'line': 'doWork(ch)' - 'name': 'doWork' - 'tokenPos': 0 - 'isFunc': true - } - { - 'line': 'f1()' - 'name': 'f1' - 'tokenPos': 0 - 'isFunc': true - } - ] - - want = ['source.go', 'support.function.go'] - - for t in tests - {tokens} = grammar.tokenizeLine t.line - - relevantToken = tokens[t.tokenPos] - if t.isFunc - expect(relevantToken).not.toBeNull() - expect(relevantToken.value).toEqual t.name - expect(relevantToken.scopes).toEqual want - - next = tokens[t.tokenPos + 1] - expect(next.value).toEqual '(' - expect(next.scopes).toEqual ['source.go', 'punctuation.definition.begin.bracket.round.go'] - else - expect(relevantToken.scopes).not.toEqual want - - it 'tokenizes package names', -> - tests = ['package main', 'package mypackage'] - - for test in tests - {tokens} = grammar.tokenizeLine test - expect(tokens[0].scopes).toEqual ['source.go', 'keyword.package.go'] - expect(tokens[2].scopes).toEqual ['source.go', 'entity.name.package.go'] - - it 'tokenizes invalid package names as such', -> - {tokens} = grammar.tokenizeLine 'package 0mypackage' - expect(tokens[0]).toEqual value: 'package', scopes: ['source.go', 'keyword.package.go'] - expect(tokens[2]).toEqual value: '0mypackage', scopes: ['source.go', 'invalid.illegal.identifier.go'] - - it 'does not treat words that have a trailing package as a package name', -> - {tokens} = grammar.tokenizeLine 'func myFunc(Varpackage string)' - expect(tokens[4]).toEqual value: 'Varpackage ', scopes: ['source.go'] - expect(tokens[5]).toEqual value: 'string', scopes: ['source.go', 'storage.type.string.go'] - - it 'tokenizes type names', -> - tests = ['type mystring string', 'type mytype interface{'] - - for test in tests - {tokens} = grammar.tokenizeLine test - expect(tokens[0].scopes).toEqual ['source.go', 'keyword.type.go'] - expect(tokens[2].scopes).toEqual ['source.go', 'entity.name.type.go'] - - it 'tokenizes invalid type names as such', -> - {tokens} = grammar.tokenizeLine 'type 0mystring string' - expect(tokens[0]).toEqual value: 'type', scopes: ['source.go', 'keyword.type.go'] - expect(tokens[2]).toEqual value: '0mystring', scopes: ['source.go', 'invalid.illegal.identifier.go'] - - it 'does not treat words that have a trailing type as a type name', -> - {tokens} = grammar.tokenizeLine 'func myFunc(Vartype string)' - expect(tokens[4]).toEqual value: 'Vartype ', scopes: ['source.go'] - expect(tokens[5]).toEqual value: 'string', scopes: ['source.go', 'storage.type.string.go'] - - describe 'in variable declarations', -> - testVar = (token) -> - expect(token.value).toBe 'var' - expect(token.scopes).toEqual ['source.go', 'keyword.var.go'] - - testVarAssignment = (token, name) -> - expect(token.value).toBe name - expect(token.scopes).toEqual ['source.go', 'variable.other.assignment.go'] - - testVarDeclaration = (token, name) -> - expect(token.value).toBe name - expect(token.scopes).toEqual ['source.go', 'variable.other.declaration.go'] - - testOp = (token, op) -> - expect(token.value).toBe op - expect(token.scopes).toEqual ['source.go', 'keyword.operator.go'] - - testOpAddress = (token, op) -> - expect(token.value).toBe op - expect(token.scopes).toEqual ['source.go', 'keyword.operator.address.go'] - - testOpAssignment = (token, op) -> - expect(token.value).toBe op - expect(token.scopes).toEqual ['source.go', 'keyword.operator.assignment.go'] - - testOpBracket = (token, op, type) -> - expect(token.value).toBe op - expect(token.scopes).toEqual ['source.go', "punctuation.definition.variables.#{type}.bracket.round.go"] - - testOpPunctuation = (token, op) -> - expect(token.value).toBe op - expect(token.scopes).toEqual ['source.go', 'punctuation.other.comma.go'] - - testOpTermination = (token, op) -> - expect(token.value).toBe op - expect(token.scopes).toEqual ['source.go', 'punctuation.terminator.go'] - - testNumType = (token, name) -> - expect(token.value).toBe name - expect(token.scopes).toEqual ['source.go', 'storage.type.numeric.go'] - - testStringType = (token, name) -> - expect(token.value).toBe name - expect(token.scopes).toEqual ['source.go', 'storage.type.string.go'] - - testNum = (token, value) -> - expect(token.value).toBe value - expect(token.scopes).toEqual ['source.go', 'constant.numeric.integer.go'] - - testString = (token, value) -> - expect(token.value).toBe value - expect(token.scopes).toEqual ['source.go', 'string.quoted.double.go'] - - describe 'in var statements', -> - it 'tokenizes a single variable assignment', -> - {tokens} = grammar.tokenizeLine 'i = 7' - testVarAssignment tokens[0], 'i' - testOpAssignment tokens[2], '=' - testNum tokens[4], '7' - - it 'tokenizes a single qualified variable assignment', -> - {tokens} = grammar.tokenizeLine 'a.b.cde = 7' - expect(tokens[0]).toEqual value: 'a', scopes: ['source.go', 'variable.other.assignment.go'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.go', 'variable.other.assignment.go'] - expect(tokens[3]).toEqual value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go'] - expect(tokens[4]).toEqual value: 'cde', scopes: ['source.go', 'variable.other.assignment.go'] - testOpAssignment tokens[6], '=' - testNum tokens[8], '7' - - it 'tokenizes multiple variable assignments', -> - {tokens} = grammar.tokenizeLine 'i, j = 7, 8' - testVarAssignment tokens[0], 'i' - testOpPunctuation tokens[1], ',' - testVarAssignment tokens[3], 'j' - testOpAssignment tokens[5], '=' - testNum tokens[7], '7' - testNum tokens[10], '8' - - it 'tokenizes multiple qualified variable assignment', -> - {tokens} = grammar.tokenizeLine 'a.b, c.d.efg = 7, 8' - expect(tokens[0]).toEqual value: 'a', scopes: ['source.go', 'variable.other.assignment.go'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go'] - expect(tokens[2]).toEqual value: 'b', scopes: ['source.go', 'variable.other.assignment.go'] - testOpPunctuation tokens[3], ',' - expect(tokens[5]).toEqual value: 'c', scopes: ['source.go', 'variable.other.assignment.go'] - expect(tokens[6]).toEqual value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go'] - expect(tokens[7]).toEqual value: 'd', scopes: ['source.go', 'variable.other.assignment.go'] - expect(tokens[8]).toEqual value: '.', scopes: ['source.go', 'variable.other.assignment.go', 'punctuation.other.period.go'] - expect(tokens[9]).toEqual value: 'efg', scopes: ['source.go', 'variable.other.assignment.go'] - testOpAssignment tokens[11], '=' - testNum tokens[13], '7' - testNum tokens[16], '8' - - it 'tokenizes a single name and a type', -> - {tokens} = grammar.tokenizeLine 'var i int' - testVar tokens[0] - testVarDeclaration tokens[2], 'i' - testNumType tokens[4], 'int' - - it 'tokenizes a name and a qualified type', -> - {tokens} = grammar.tokenizeLine 'var a b.c' - testVar tokens[0] - expect(tokens[2]).toEqual value: 'a', scopes: ['source.go', 'variable.other.declaration.go'] - expect(tokens[3]).toEqual value: ' b', scopes: ['source.go'] - expect(tokens[4]).toEqual value: '.', scopes: ['source.go', 'punctuation.other.period.go'] - expect(tokens[5]).toEqual value: 'c', scopes: ['source.go'] - - it 'tokenizes a single name and an array type', -> - {tokens} = grammar.tokenizeLine 'var s []string' - testVar tokens[0] - testVarDeclaration tokens[2], 's' - testStringType tokens[6], 'string' - - it 'tokenizes a single name and an array type with predetermined length', -> - {tokens} = grammar.tokenizeLine 'var s [4]string' - testVar tokens[0] - testVarDeclaration tokens[2], 's' - expect(tokens[4]).toEqual value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - expect(tokens[5]).toEqual value: '4', scopes: ['source.go', 'constant.numeric.integer.go'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - testStringType tokens[7], 'string' - - it 'tokenizes a single name and an array type with variadic length', -> - {tokens} = grammar.tokenizeLine 'var s [...]string' - testVar tokens[0] - testVarDeclaration tokens[2], 's' - expect(tokens[4]).toEqual value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - expect(tokens[5]).toEqual value: '...', scopes: ['source.go', 'keyword.operator.ellipsis.go'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - testStringType tokens[7], 'string' - - it 'tokenizes a single name and multi-dimensional types with an address', -> - {tokens} = grammar.tokenizeLine 'var e [][]*string' - testVar tokens[0] - testVarDeclaration tokens[2], 'e' - expect(tokens[4]).toEqual value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - expect(tokens[5]).toEqual value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - expect(tokens[6]).toEqual value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - expect(tokens[7]).toEqual value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go'] - testOpAddress tokens[8], '*' - testStringType tokens[9], 'string' - - it 'tokenizes a single name and a channel', -> - {tokens} = grammar.tokenizeLine 'var x <-chan bool' - testVar tokens[0] - testVarDeclaration tokens[2], 'x' - expect(tokens[4]).toEqual value: '<-', scopes: ['source.go', 'keyword.operator.channel.go'] - expect(tokens[5]).toEqual value: 'chan', scopes: ['source.go', 'keyword.channel.go'] - expect(tokens[7]).toEqual value: 'bool', scopes: ['source.go', 'storage.type.boolean.go'] - - it 'tokenizes a single name and its initialization', -> - {tokens} = grammar.tokenizeLine ' var k = 0' - testVar tokens[1] - testVarAssignment tokens[3], 'k' - testOpAssignment tokens[5], '=' - testNum tokens[7], '0' - - it 'tokenizes a single name, a type, and an initialization', -> - {tokens} = grammar.tokenizeLine 'var z blub = 7' - testVar tokens[0] - testVarAssignment tokens[2], 'z' - expect(tokens[3]).toEqual value: ' blub ', scopes: ['source.go'] - testOpAssignment tokens[4], '=' - testNum tokens[6], '7' - - it 'tokenizes a single name, a qualified type, and an initialization', -> - {tokens} = grammar.tokenizeLine 'var a b.c = 5' - testVar tokens[0] - expect(tokens[2]).toEqual value: 'a', scopes: ['source.go', 'variable.other.assignment.go'] - expect(tokens[3]).toEqual value: ' b', scopes: ['source.go'] - expect(tokens[4]).toEqual value: '.', scopes: ['source.go', 'punctuation.other.period.go'] - expect(tokens[5]).toEqual value: 'c ', scopes: ['source.go'] - testOpAssignment tokens[6], '=' - testNum tokens[8], '5' - - it 'does not tokenize more than necessary', -> - # This test is worded vaguely because it's hard to describe. - # Basically, make sure that the variable match isn't tokenizing the entire line - # in a (=.+) style match. This prevents multiline stuff after the assignment - # from working correctly, because match can only tokenize single lines. - lines = grammar.tokenizeLines ''' - var multiline string = `wow! - this should work!` - ''' - testVar lines[0][0] - testVarAssignment lines[0][2], 'multiline' - testStringType lines[0][4], 'string' - testOpAssignment lines[0][6], '=' - expect(lines[0][8]).toEqual value: '`', scopes: ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.begin.go'] - expect(lines[1][1]).toEqual value: '`', scopes: ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.end.go'] - - it 'tokenizes multiple names and a type', -> - {tokens} = grammar.tokenizeLine 'var U, V, W float64' - testVar tokens[0] - testVarDeclaration tokens[2], 'U' - testOpPunctuation tokens[3], ',' - testVarDeclaration tokens[5], 'V' - testOpPunctuation tokens[6], ',' - testVarDeclaration tokens[8], 'W' - - it 'tokenizes multiple names and a qualified type', -> - {tokens} = grammar.tokenizeLine 'var a, b c.d' - testVar tokens[0] - expect(tokens[2]).toEqual value: 'a', scopes: ['source.go', 'variable.other.declaration.go'] - testOpPunctuation tokens[3], ',' - expect(tokens[5]).toEqual value: 'b', scopes: ['source.go', 'variable.other.declaration.go'] - expect(tokens[6]).toEqual value: ' c', scopes: ['source.go'] - expect(tokens[7]).toEqual value: '.', scopes: ['source.go', 'punctuation.other.period.go'] - expect(tokens[8]).toEqual value: 'd', scopes: ['source.go'] - - it 'tokenizes multiple names and initialization expressions', -> - {tokens} = grammar.tokenizeLine 'var x, y, z = 1, 2, 3' - testVar tokens[0] - testVarAssignment tokens[2], 'x' - testOpPunctuation tokens[3], ',' - testVarAssignment tokens[5], 'y' - testOpPunctuation tokens[6], ',' - testVarAssignment tokens[8], 'z' - testOpAssignment tokens[10], '=' - testNum tokens[12], '1' - testOpPunctuation tokens[13], ',' - testNum tokens[15], '2' - testOpPunctuation tokens[16], ',' - testNum tokens[18], '3' - - it 'tokenizes multiple names, a type, and initialization expressions', -> - {tokens} = grammar.tokenizeLine 'var x, y float32 = float, thirtytwo' - testVar tokens[0] - testVarAssignment tokens[2], 'x' - testOpPunctuation tokens[3], ',' - testVarAssignment tokens[5], 'y' - testNumType tokens[7], 'float32' - testOpAssignment tokens[9], '=' - testOpPunctuation tokens[11], ',' - - it 'tokenizes multiple names, a qualified type, and initialization expression', -> - {tokens} = grammar.tokenizeLine 'var a, b c.d = 1, 2' - testVar tokens[0] - expect(tokens[2]).toEqual value: 'a', scopes: ['source.go', 'variable.other.assignment.go'] - testOpPunctuation tokens[3], ',' - expect(tokens[5]).toEqual value: 'b', scopes: ['source.go', 'variable.other.assignment.go'] - expect(tokens[6]).toEqual value: ' c', scopes: ['source.go'] - expect(tokens[7]).toEqual value: '.', scopes: ['source.go', 'punctuation.other.period.go'] - expect(tokens[8]).toEqual value: 'd ', scopes: ['source.go'] - testOpAssignment tokens[9], '=' - testNum tokens[11], '1' - testOpPunctuation tokens[12], ',' - testNum tokens[14], '2' - - it 'tokenizes multiple names and a function call', -> - {tokens} = grammar.tokenizeLine 'var re, im = complexSqrt(-1)' - testVar tokens[0] - testVarAssignment tokens[2], 're' - testVarAssignment tokens[5], 'im' - testOpAssignment tokens[7], '=' - - it 'tokenizes with a placeholder', -> - {tokens} = grammar.tokenizeLine 'var _, found = entries[name]' - testVar tokens[0] - testVarAssignment tokens[2], '_' - testVarAssignment tokens[5], 'found' - testOpAssignment tokens[7], '=' - - it 'does not treat words that have a trailing var as a variable declaration', -> - {tokens} = grammar.tokenizeLine 'func test(envvar string)' - expect(tokens[4]).toEqual value: 'envvar ', scopes: ['source.go'] - expect(tokens[5]).toEqual value: 'string', scopes: ['source.go', 'storage.type.string.go'] - - describe 'in var statement blocks', -> - it 'tokenizes single names with a type', -> - lines = grammar.tokenizeLines ''' - var ( - foo *bar - ) - ''' - testVar lines[0][0] - testOpBracket lines[0][2], '(', 'begin' - testVarDeclaration lines[1][1], 'foo' - testOpAddress lines[1][3], '*' - testOpBracket lines[2][0], ')', 'end' - - it 'tokenizes single names with an initializer', -> - lines = grammar.tokenizeLines ''' - var ( - foo = 42 - ) - ''' - testVar lines[0][0], 'var' - testOpBracket lines[0][2], '(', 'begin' - testVarAssignment lines[1][1], 'foo' - testOpAssignment lines[1][3], '=' - testNum lines[1][5], '42' - testOpBracket lines[2][0], ')', 'end' - - it 'tokenizes multiple names', -> - lines = grammar.tokenizeLines ''' - var ( - foo, bar = baz, quux - ) - ''' - testVar lines[0][0] - testOpBracket lines[0][2], '(', 'begin' - testVarAssignment lines[1][1], 'foo' - testOpPunctuation lines[1][2], ',' - testVarAssignment lines[1][4], 'bar' - testOpAssignment lines[1][6], '=' - testOpPunctuation lines[1][8], ',' - testOpBracket lines[2][0], ')', 'end' - - it 'tokenizes non variable declarations', -> - lines = grammar.tokenizeLines ''' - var ( - // I am a comment - foo *bar - userRegister = &routers.Handler{ - Handler: func(c echo.Context) error { - if err := userService.Register(&user); err != nil { - return err - } - return nil - }, - } - ) - ''' - testVar lines[0][0] - testOpBracket lines[0][2], '(', 'begin' - expect(lines[1][1]).toEqual value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go'] - expect(lines[1][2]).toEqual value: ' I am a comment', scopes: ['source.go', 'comment.line.double-slash.go'] - testVarDeclaration lines[2][1], 'foo' - testOpAddress lines[2][3], '*' - testVarAssignment lines[3][1], 'userRegister' - expect(lines[4][3]).toEqual value: 'func', scopes: ['source.go', 'keyword.function.go'] - expect(lines[5][1]).toEqual value: 'if', scopes: ['source.go', 'keyword.control.go'] - expect(lines[8][3]).toEqual value: 'nil', scopes: ['source.go', 'constant.language.go'] - testOpBracket lines[11][0], ')', 'end' - - it 'tokenizes all parts of variable initializations correctly', -> - lines = grammar.tokenizeLines ''' - var ( - m = map[string]int{ - "key": 10, - } - ) - ''' - testVar lines[0][0] - testOpBracket lines[0][2], '(', 'begin' - testVarAssignment lines[1][1], 'm' - testOpAssignment lines[1][3], '=' - testString lines[2][2], 'key' - testNum lines[2][6], '10' - testOpBracket lines[4][0], ')', 'end' - - it 'tokenizes non-ASCII variable names', -> - {tokens} = grammar.tokenizeLine 'über = test' - testVarAssignment tokens[0], 'über' - testOpAssignment tokens[2], '=' - - it 'tokenizes invalid variable names as such', -> - {tokens} = grammar.tokenizeLine 'var 0test = 0' - testVar tokens[0] - expect(tokens[2]).toEqual value: '0test', scopes: ['source.go', 'invalid.illegal.identifier.go'] - - describe 'in shorthand variable declarations', -> - it 'tokenizes single names', -> - {tokens} = grammar.tokenizeLine 'f := func() int { return 7 }' - testVarAssignment tokens[0], 'f' - testOpAssignment tokens[2], ':=' - - {tokens} = grammar.tokenizeLine 'ch := make(chan int)' - testVarAssignment tokens[0], 'ch' - testOpAssignment tokens[2], ':=' - - it 'tokenizes multiple names', -> - {tokens} = grammar.tokenizeLine 'i, j := 0, 10' - testVarAssignment tokens[0], 'i' - testOpPunctuation tokens[1], ',' - testVarAssignment tokens[3], 'j' - - {tokens} = grammar.tokenizeLine 'if _, y, z := coord(p); z > 0' - testVarAssignment tokens[2], '_' - testVarAssignment tokens[5], 'y' - testVarAssignment tokens[8], 'z' - testOpAssignment tokens[10], ':=' - testOpTermination tokens[16], ';' - - describe 'in imports declarations', -> - testImport = (token) -> - expect(token.value).toBe 'import' - expect(token.scopes).toEqual ['source.go', 'keyword.import.go'] - - testImportAlias = (token, name) -> - expect(token.value).toBe name - expect(token.scopes).toEqual ['source.go', 'entity.alias.import.go'] - - testImportPackage = (token, name) -> - expect(token.value).toBe name - expect(token.scopes).toEqual ['source.go', 'string.quoted.double.go', 'entity.name.import.go'] - - testOpBracket = (token, op, type) -> - expect(token.value).toBe op - expect(token.scopes).toEqual ['source.go', "punctuation.definition.imports.#{type}.bracket.round.go"] - - testBeginQuoted = (token) -> - expect(token.value).toBe '"' - expect(token.scopes).toEqual ['source.go', 'string.quoted.double.go', 'punctuation.definition.string.begin.go'] - - testEndQuoted = (token) -> - expect(token.value).toBe '"' - expect(token.scopes).toEqual ['source.go', 'string.quoted.double.go', 'punctuation.definition.string.end.go'] - - describe 'when it is a single line declaration', -> - it 'tokenizes declarations with a package name', -> - {tokens} = grammar.tokenizeLine 'import "fmt"' - testImport tokens[0] - testBeginQuoted tokens[2] - testImportPackage tokens[3], 'fmt' - testEndQuoted tokens[4] - - it 'tokenizes declarations with a package name and an alias', -> - {tokens} = grammar.tokenizeLine 'import . "fmt"' - testImport tokens[0] - testImportAlias tokens[2], '.' - testBeginQuoted tokens[4] - testImportPackage tokens[5], 'fmt' - testEndQuoted tokens[6] - {tokens} = grammar.tokenizeLine 'import otherpackage "github.com/test/package"' - testImport tokens[0] - testImportAlias tokens[2], 'otherpackage' - testBeginQuoted tokens[4] - testImportPackage tokens[5], 'github.com/test/package' - testEndQuoted tokens[6] - - it 'does not treat words that have a trailing import as a import declaration', -> - {tokens} = grammar.tokenizeLine 'func myFunc(Varimport string)' - expect(tokens[4]).toEqual value: 'Varimport ', scopes: ['source.go'] - expect(tokens[5]).toEqual value: 'string', scopes: ['source.go', 'storage.type.string.go'] - - describe 'when it is a multi line declaration', -> - it 'tokenizes single declarations with a package name', -> - [kwd, decl, closing] = grammar.tokenizeLines ''' - import ( - "github.com/test/package" - ) - ''' - testImport kwd[0] - testOpBracket kwd[2], '(', 'begin' - testBeginQuoted decl[1] - testImportPackage decl[2], 'github.com/test/package' - testEndQuoted decl[3] - testOpBracket closing[0], ')', 'end' - - it 'tokenizes multiple declarations with a package name', -> - [kwd, decl, decl2, closing] = grammar.tokenizeLines ''' - import ( - "github.com/test/package" - "fmt" - ) - ''' - testImport kwd[0] - testOpBracket kwd[2], '(', 'begin' - testBeginQuoted decl[1] - testImportPackage decl[2], 'github.com/test/package' - testEndQuoted decl[3] - testBeginQuoted decl2[1] - testImportPackage decl2[2], 'fmt' - testEndQuoted decl2[3] - testOpBracket closing[0], ')', 'end' - - it 'tokenizes single imports with an alias for a multi-line declaration', -> - [kwd, decl, closing] = grammar.tokenizeLines ''' - import ( - . "github.com/test/package" - ) - ''' - testImport kwd[0] - testOpBracket kwd[2], '(', 'begin' - testImportAlias decl[1], '.' - testBeginQuoted decl[3] - testImportPackage decl[4], 'github.com/test/package' - testEndQuoted decl[5] - testOpBracket closing[0], ')', 'end' - - it 'tokenizes multiple imports with an alias for a multi-line declaration', -> - [kwd, decl, decl2, closing] = grammar.tokenizeLines ''' - import ( - . "github.com/test/package" - "fmt" - ) - ''' - testImport kwd[0] - testOpBracket kwd[2], '(', 'begin' - testImportAlias decl[1], '.' - testBeginQuoted decl[3] - testImportPackage decl[4], 'github.com/test/package' - testEndQuoted decl[5] - testBeginQuoted decl2[1] - testImportPackage decl2[2], 'fmt' - testEndQuoted decl2[3] - testOpBracket closing[0], ')', 'end' diff --git a/packages/language-go/spec/go-spec.js b/packages/language-go/spec/go-spec.js index 72c6b68695..beb8ead8c5 100644 --- a/packages/language-go/spec/go-spec.js +++ b/packages/language-go/spec/go-spec.js @@ -1,10 +1,4 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS205: Consider reworking code to avoid use of IIFEs - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe('Go grammar', function() { let grammar = null; @@ -13,12 +7,12 @@ describe('Go grammar', function() { waitsForPromise(() => atom.packages.activatePackage('language-go')); - return runs(() => grammar = atom.grammars.grammarForScopeName('source.go')); + runs(() => grammar = atom.grammars.grammarForScopeName('source.go')); }); it('parses the grammar', function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe('source.go'); + expect(grammar.scopeName).toBe('source.go'); }); it('tokenizes comments', function() { @@ -34,7 +28,7 @@ describe('Go grammar', function() { expect(tokens[1][0].value).toEqual('I am a comment'); expect(tokens[1][0].scopes).toEqual(['source.go', 'comment.block.go']); expect(tokens[2][0].value).toEqual('*/'); - return expect(tokens[2][0].scopes).toEqual(['source.go', 'comment.block.go', 'punctuation.definition.comment.go']); + expect(tokens[2][0].scopes).toEqual(['source.go', 'comment.block.go', 'punctuation.definition.comment.go']); }); it('tokenizes comments in imports', function() { @@ -48,7 +42,7 @@ import ( ); expect(lines[1][1]).toEqual({value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']}); expect(lines[2][5]).toEqual({value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']}); - return expect(lines[3][1]).toEqual({value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']}); + expect(lines[3][1]).toEqual({value: '//', scopes: ['source.go', 'comment.line.double-slash.go', 'punctuation.definition.comment.go']}); }); it('tokenizes strings', function() { @@ -113,7 +107,7 @@ import ( ({tokens} = grammar.tokenizeLine('"\\""')); expect(tokens[1].value).toEqual('\\"'); - return expect(tokens[1].scopes).toEqual(['source.go', 'string.quoted.double.go', 'constant.character.escape.go']); + expect(tokens[1].scopes).toEqual(['source.go', 'string.quoted.double.go', 'constant.character.escape.go']); }); it('tokenizes placeholders in raw strings', function() { @@ -174,7 +168,7 @@ import ( ({tokens} = grammar.tokenizeLine("'some single quote string'")); expect(tokens[0]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.begin.go']}); expect(tokens[1]).toEqual({value: 'some single quote string', scopes: ['source.go', 'string.quoted.rune.go', 'invalid.illegal.unknown-rune.go']}); - return expect(tokens[2]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go']}); + expect(tokens[2]).toEqual({value: "'", scopes: ['source.go', 'string.quoted.rune.go', 'punctuation.definition.string.end.go']}); }); it('tokenizes invalid whitespace around chan annotations', function() { @@ -503,7 +497,7 @@ import ( expect(tokens[2]).toEqual({value: '3.0', scopes: ['source.go', 'constant.numeric.floating-point.go']}); expect(tokens[6]).toEqual({value: '12', scopes: ['source.go', 'constant.numeric.integer.go']}); expect(tokens[7]).toEqual({value: '>', scopes: ['source.go', 'keyword.operator.comparison.go']}); - return expect(tokens[8]).toEqual({value: 'bar', scopes: ['source.go']}); + expect(tokens[8]).toEqual({value: 'bar', scopes: ['source.go']}); }); it('tokenizes punctuation brackets', function() { @@ -513,7 +507,7 @@ import ( expect(tokens[2]).toEqual({value: '[', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); expect(tokens[3]).toEqual({value: ']', scopes: ['source.go', 'punctuation.definition.bracket.square.go']}); expect(tokens[4]).toEqual({value: ')', scopes: ['source.go', 'punctuation.definition.end.bracket.round.go']}); - return expect(tokens[5]).toEqual({value: '}', scopes: ['source.go', 'punctuation.definition.end.bracket.curly.go']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.go', 'punctuation.definition.end.bracket.curly.go']}); }); it('tokenizes punctuation delimiters', function() { @@ -616,13 +610,13 @@ import ( it('tokenizes invalid package names as such', function() { const {tokens} = grammar.tokenizeLine('package 0mypackage'); expect(tokens[0]).toEqual({value: 'package', scopes: ['source.go', 'keyword.package.go']}); - return expect(tokens[2]).toEqual({value: '0mypackage', scopes: ['source.go', 'invalid.illegal.identifier.go']}); + expect(tokens[2]).toEqual({value: '0mypackage', scopes: ['source.go', 'invalid.illegal.identifier.go']}); }); it('does not treat words that have a trailing package as a package name', function() { const {tokens} = grammar.tokenizeLine('func myFunc(Varpackage string)'); expect(tokens[4]).toEqual({value: 'Varpackage ', scopes: ['source.go']}); - return expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); + expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); }); it('tokenizes type names', function() { @@ -642,82 +636,82 @@ import ( it('tokenizes invalid type names as such', function() { const {tokens} = grammar.tokenizeLine('type 0mystring string'); expect(tokens[0]).toEqual({value: 'type', scopes: ['source.go', 'keyword.type.go']}); - return expect(tokens[2]).toEqual({value: '0mystring', scopes: ['source.go', 'invalid.illegal.identifier.go']}); + expect(tokens[2]).toEqual({value: '0mystring', scopes: ['source.go', 'invalid.illegal.identifier.go']}); }); it('does not treat words that have a trailing type as a type name', function() { const {tokens} = grammar.tokenizeLine('func myFunc(Vartype string)'); expect(tokens[4]).toEqual({value: 'Vartype ', scopes: ['source.go']}); - return expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); + expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); }); describe('in variable declarations', function() { const testVar = function(token) { expect(token.value).toBe('var'); - return expect(token.scopes).toEqual(['source.go', 'keyword.var.go']); + expect(token.scopes).toEqual(['source.go', 'keyword.var.go']); }; const testVarAssignment = function(token, name) { expect(token.value).toBe(name); - return expect(token.scopes).toEqual(['source.go', 'variable.other.assignment.go']); + expect(token.scopes).toEqual(['source.go', 'variable.other.assignment.go']); }; const testVarDeclaration = function(token, name) { expect(token.value).toBe(name); - return expect(token.scopes).toEqual(['source.go', 'variable.other.declaration.go']); + expect(token.scopes).toEqual(['source.go', 'variable.other.declaration.go']); }; const testOp = function(token, op) { expect(token.value).toBe(op); - return expect(token.scopes).toEqual(['source.go', 'keyword.operator.go']); + expect(token.scopes).toEqual(['source.go', 'keyword.operator.go']); }; const testOpAddress = function(token, op) { expect(token.value).toBe(op); - return expect(token.scopes).toEqual(['source.go', 'keyword.operator.address.go']); + expect(token.scopes).toEqual(['source.go', 'keyword.operator.address.go']); }; const testOpAssignment = function(token, op) { expect(token.value).toBe(op); - return expect(token.scopes).toEqual(['source.go', 'keyword.operator.assignment.go']); + expect(token.scopes).toEqual(['source.go', 'keyword.operator.assignment.go']); }; const testOpBracket = function(token, op, type) { expect(token.value).toBe(op); - return expect(token.scopes).toEqual(['source.go', `punctuation.definition.variables.${type}.bracket.round.go`]); + expect(token.scopes).toEqual(['source.go', `punctuation.definition.variables.${type}.bracket.round.go`]); }; const testOpPunctuation = function(token, op) { expect(token.value).toBe(op); - return expect(token.scopes).toEqual(['source.go', 'punctuation.other.comma.go']); + expect(token.scopes).toEqual(['source.go', 'punctuation.other.comma.go']); }; const testOpTermination = function(token, op) { expect(token.value).toBe(op); - return expect(token.scopes).toEqual(['source.go', 'punctuation.terminator.go']); + expect(token.scopes).toEqual(['source.go', 'punctuation.terminator.go']); }; const testNumType = function(token, name) { expect(token.value).toBe(name); - return expect(token.scopes).toEqual(['source.go', 'storage.type.numeric.go']); + expect(token.scopes).toEqual(['source.go', 'storage.type.numeric.go']); }; const testStringType = function(token, name) { expect(token.value).toBe(name); - return expect(token.scopes).toEqual(['source.go', 'storage.type.string.go']); + expect(token.scopes).toEqual(['source.go', 'storage.type.string.go']); }; const testNum = function(token, value) { expect(token.value).toBe(value); - return expect(token.scopes).toEqual(['source.go', 'constant.numeric.integer.go']); + expect(token.scopes).toEqual(['source.go', 'constant.numeric.integer.go']); }; const testString = function(token, value) { expect(token.value).toBe(value); - return expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go']); + expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go']); }; - return describe('in var statements', function() { + describe('in var statements', function() { it('tokenizes a single variable assignment', function() { const {tokens} = grammar.tokenizeLine('i = 7'); testVarAssignment(tokens[0], 'i'); @@ -775,7 +769,7 @@ import ( expect(tokens[2]).toEqual({value: 'a', scopes: ['source.go', 'variable.other.declaration.go']}); expect(tokens[3]).toEqual({value: ' b', scopes: ['source.go']}); expect(tokens[4]).toEqual({value: '.', scopes: ['source.go', 'punctuation.other.period.go']}); - return expect(tokens[5]).toEqual({value: 'c', scopes: ['source.go']}); + expect(tokens[5]).toEqual({value: 'c', scopes: ['source.go']}); }); it('tokenizes a single name and an array type', function() { @@ -823,7 +817,7 @@ import ( testVarDeclaration(tokens[2], 'x'); expect(tokens[4]).toEqual({value: '<-', scopes: ['source.go', 'keyword.operator.channel.go']}); expect(tokens[5]).toEqual({value: 'chan', scopes: ['source.go', 'keyword.channel.go']}); - return expect(tokens[7]).toEqual({value: 'bool', scopes: ['source.go', 'storage.type.boolean.go']}); + expect(tokens[7]).toEqual({value: 'bool', scopes: ['source.go', 'storage.type.boolean.go']}); }); it('tokenizes a single name and its initialization', function() { @@ -869,7 +863,7 @@ this should work!\`\ testStringType(lines[0][4], 'string'); testOpAssignment(lines[0][6], '='); expect(lines[0][8]).toEqual({value: '`', scopes: ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.begin.go']}); - return expect(lines[1][1]).toEqual({value: '`', scopes: ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.end.go']}); + expect(lines[1][1]).toEqual({value: '`', scopes: ['source.go', 'string.quoted.raw.go', 'punctuation.definition.string.end.go']}); }); it('tokenizes multiple names and a type', function() { @@ -890,7 +884,7 @@ this should work!\`\ expect(tokens[5]).toEqual({value: 'b', scopes: ['source.go', 'variable.other.declaration.go']}); expect(tokens[6]).toEqual({value: ' c', scopes: ['source.go']}); expect(tokens[7]).toEqual({value: '.', scopes: ['source.go', 'punctuation.other.period.go']}); - return expect(tokens[8]).toEqual({value: 'd', scopes: ['source.go']}); + expect(tokens[8]).toEqual({value: 'd', scopes: ['source.go']}); }); it('tokenizes multiple names and initialization expressions', function() { @@ -954,7 +948,7 @@ this should work!\`\ it('does not treat words that have a trailing var as a variable declaration', function() { const {tokens} = grammar.tokenizeLine('func test(envvar string)'); expect(tokens[4]).toEqual({value: 'envvar ', scopes: ['source.go']}); - return expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); + expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); }); describe('in var statement blocks', function() { @@ -1033,7 +1027,7 @@ var ( return testOpBracket(lines[11][0], ')', 'end'); }); - return it('tokenizes all parts of variable initializations correctly', function() { + it('tokenizes all parts of variable initializations correctly', function() { const lines = grammar.tokenizeLines(`\ var ( m = map[string]int{ @@ -1061,10 +1055,10 @@ var ( it('tokenizes invalid variable names as such', function() { const {tokens} = grammar.tokenizeLine('var 0test = 0'); testVar(tokens[0]); - return expect(tokens[2]).toEqual({value: '0test', scopes: ['source.go', 'invalid.illegal.identifier.go']}); + expect(tokens[2]).toEqual({value: '0test', scopes: ['source.go', 'invalid.illegal.identifier.go']}); }); - return describe('in shorthand variable declarations', function() { + describe('in shorthand variable declarations', function() { it('tokenizes single names', function() { let {tokens} = grammar.tokenizeLine('f := func() int { return 7 }'); testVarAssignment(tokens[0], 'f'); @@ -1075,7 +1069,7 @@ var ( return testOpAssignment(tokens[2], ':='); }); - return it('tokenizes multiple names', function() { + it('tokenizes multiple names', function() { let {tokens} = grammar.tokenizeLine('i, j := 0, 10'); testVarAssignment(tokens[0], 'i'); testOpPunctuation(tokens[1], ','); @@ -1092,35 +1086,35 @@ var ( }); }); - return describe('in imports declarations', function() { + describe('in imports declarations', function() { const testImport = function(token) { expect(token.value).toBe('import'); - return expect(token.scopes).toEqual(['source.go', 'keyword.import.go']); + expect(token.scopes).toEqual(['source.go', 'keyword.import.go']); }; const testImportAlias = function(token, name) { expect(token.value).toBe(name); - return expect(token.scopes).toEqual(['source.go', 'entity.alias.import.go']); + expect(token.scopes).toEqual(['source.go', 'entity.alias.import.go']); }; const testImportPackage = function(token, name) { expect(token.value).toBe(name); - return expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'entity.name.import.go']); + expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'entity.name.import.go']); }; const testOpBracket = function(token, op, type) { expect(token.value).toBe(op); - return expect(token.scopes).toEqual(['source.go', `punctuation.definition.imports.${type}.bracket.round.go`]); + expect(token.scopes).toEqual(['source.go', `punctuation.definition.imports.${type}.bracket.round.go`]); }; const testBeginQuoted = function(token) { expect(token.value).toBe('"'); - return expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'punctuation.definition.string.begin.go']); + expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'punctuation.definition.string.begin.go']); }; const testEndQuoted = function(token) { expect(token.value).toBe('"'); - return expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'punctuation.definition.string.end.go']); + expect(token.scopes).toEqual(['source.go', 'string.quoted.double.go', 'punctuation.definition.string.end.go']); }; describe('when it is a single line declaration', function() { @@ -1147,14 +1141,14 @@ var ( return testEndQuoted(tokens[6]); }); - return it('does not treat words that have a trailing import as a import declaration', function() { + it('does not treat words that have a trailing import as a import declaration', function() { const {tokens} = grammar.tokenizeLine('func myFunc(Varimport string)'); expect(tokens[4]).toEqual({value: 'Varimport ', scopes: ['source.go']}); - return expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); + expect(tokens[5]).toEqual({value: 'string', scopes: ['source.go', 'storage.type.string.go']}); }); }); - return describe('when it is a multi line declaration', function() { + describe('when it is a multi line declaration', function() { it('tokenizes single declarations with a package name', function() { const [kwd, decl, closing] = Array.from(grammar.tokenizeLines(`\ import ( @@ -1205,7 +1199,7 @@ import ( return testOpBracket(closing[0], ')', 'end'); }); - return it('tokenizes multiple imports with an alias for a multi-line declaration', function() { + it('tokenizes multiple imports with an alias for a multi-line declaration', function() { const [kwd, decl, decl2, closing] = Array.from(grammar.tokenizeLines(`\ import ( . "github.com/test/package" diff --git a/packages/language-go/spec/language-go-spec.coffee b/packages/language-go/spec/language-go-spec.coffee deleted file mode 100644 index 9247c89998..0000000000 --- a/packages/language-go/spec/language-go-spec.coffee +++ /dev/null @@ -1,63 +0,0 @@ -describe 'Go settings', -> - [editor, languageMode] = [] - - afterEach -> - editor.destroy() - - beforeEach -> - atom.config.set 'core.useTreeSitterParsers', false - - - waitsForPromise -> - atom.workspace.open().then (o) -> - editor = o - languageMode = editor.languageMode - - waitsForPromise -> - atom.packages.activatePackage('language-go') - - it 'matches lines correctly using the increaseIndentPattern', -> - increaseIndentRegex = languageMode.increaseIndentRegexForScopeDescriptor(['source.go']) - - expect(increaseIndentRegex.findNextMatchSync(' case true:')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' default:')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync('func something() {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' if true {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' else {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' switch {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' switch true {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' select {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' select true {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' for v := range val {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' for i := 0; i < 10; i++ {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' for i := 0; i < 10; i++ {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' type something struct {')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' fmt.Printf("some%s",')).toBeTruthy() - expect(increaseIndentRegex.findNextMatchSync(' aSlice := []string{}{')).toBeTruthy() - - it 'matches lines correctly using the decreaseIndentPattern', -> - decreaseIndentRegex = languageMode.decreaseIndentRegexForScopeDescriptor(['source.go']) - - expect(decreaseIndentRegex.findNextMatchSync(' case true:')).toBeTruthy() - expect(decreaseIndentRegex.findNextMatchSync(' default:')).toBeTruthy() - expect(decreaseIndentRegex.findNextMatchSync(' }')).toBeTruthy() - expect(decreaseIndentRegex.findNextMatchSync(' },')).toBeTruthy() - expect(decreaseIndentRegex.findNextMatchSync(' )')).toBeTruthy() - expect(decreaseIndentRegex.findNextMatchSync(' ),')).toBeTruthy() - - it 'matches lines correctly using the decreaseNextIndentPattern', -> - decreaseNextIndentRegex = languageMode.decreaseNextIndentRegexForScopeDescriptor(['source.go']) - - expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something"))')).toBeTruthy() - expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something")),')).toBeTruthy() - expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something"), "x"),')).toBeTruthy() - expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println(fmt.Sprint("something"))),')).toBeTruthy() - expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println(fmt.Sprint("something"), "x")),')).toBeTruthy() - - expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something")')).toBeFalsy() - expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something"),')).toBeFalsy() - - # a line with many (), testing for catastrophic backtracking. - # see https://github.com/atom/language-go/issues/78 - longLine = 'first.second().third().fourth().fifth().sixth().seventh().eighth().ninth().tenth()' - expect(decreaseNextIndentRegex.findNextMatchSync(longLine)).toBeFalsy() diff --git a/packages/language-go/spec/language-go-spec.js b/packages/language-go/spec/language-go-spec.js index 5b5aff7dcc..4257ab9716 100644 --- a/packages/language-go/spec/language-go-spec.js +++ b/packages/language-go/spec/language-go-spec.js @@ -1,9 +1,4 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe('Go settings', function() { let [editor, languageMode] = Array.from([]); @@ -18,7 +13,7 @@ describe('Go settings', function() { return languageMode = editor.languageMode; })); - return waitsForPromise(() => atom.packages.activatePackage('language-go')); + waitsForPromise(() => atom.packages.activatePackage('language-go')); }); it('matches lines correctly using the increaseIndentPattern', function() { @@ -38,7 +33,7 @@ describe('Go settings', function() { expect(increaseIndentRegex.findNextMatchSync(' for i := 0; i < 10; i++ {')).toBeTruthy(); expect(increaseIndentRegex.findNextMatchSync(' type something struct {')).toBeTruthy(); expect(increaseIndentRegex.findNextMatchSync(' fmt.Printf("some%s",')).toBeTruthy(); - return expect(increaseIndentRegex.findNextMatchSync(' aSlice := []string{}{')).toBeTruthy(); + expect(increaseIndentRegex.findNextMatchSync(' aSlice := []string{}{')).toBeTruthy(); }); it('matches lines correctly using the decreaseIndentPattern', function() { @@ -49,10 +44,10 @@ describe('Go settings', function() { expect(decreaseIndentRegex.findNextMatchSync(' }')).toBeTruthy(); expect(decreaseIndentRegex.findNextMatchSync(' },')).toBeTruthy(); expect(decreaseIndentRegex.findNextMatchSync(' )')).toBeTruthy(); - return expect(decreaseIndentRegex.findNextMatchSync(' ),')).toBeTruthy(); + expect(decreaseIndentRegex.findNextMatchSync(' ),')).toBeTruthy(); }); - return it('matches lines correctly using the decreaseNextIndentPattern', function() { + it('matches lines correctly using the decreaseNextIndentPattern', function() { const decreaseNextIndentRegex = languageMode.decreaseNextIndentRegexForScopeDescriptor(['source.go']); expect(decreaseNextIndentRegex.findNextMatchSync(' fmt.Println("something"))')).toBeTruthy(); @@ -67,6 +62,6 @@ describe('Go settings', function() { // a line with many (), testing for catastrophic backtracking. // see https://github.com/atom/language-go/issues/78 const longLine = 'first.second().third().fourth().fifth().sixth().seventh().eighth().ninth().tenth()'; - return expect(decreaseNextIndentRegex.findNextMatchSync(longLine)).toBeFalsy(); + expect(decreaseNextIndentRegex.findNextMatchSync(longLine)).toBeFalsy(); }); }); From 3156dbfbb4a2bb44acf223f9743fbd2b36d3687a Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sun, 9 Jul 2023 21:42:23 -0700 Subject: [PATCH 11/18] Revert "Decaf `language-css`" This reverts commit d51de562164dba006dad55f7573890abc4562cc7. --- packages/language-css/spec/css-spec.coffee | 3638 ++++++++++++++++++++ packages/language-css/spec/css-spec.js | 494 +-- 2 files changed, 3888 insertions(+), 244 deletions(-) create mode 100644 packages/language-css/spec/css-spec.coffee diff --git a/packages/language-css/spec/css-spec.coffee b/packages/language-css/spec/css-spec.coffee new file mode 100644 index 0000000000..66d14a3e09 --- /dev/null +++ b/packages/language-css/spec/css-spec.coffee @@ -0,0 +1,3638 @@ +describe 'CSS grammar', -> + grammar = null + + beforeEach -> + atom.config.set 'core.useTreeSitterParsers', false + + waitsForPromise -> + atom.packages.activatePackage('language-css') + + runs -> + grammar = atom.grammars.grammarForScopeName('source.css') + + it 'parses the grammar', -> + expect(grammar).toBeTruthy() + expect(grammar.scopeName).toBe 'source.css' + + describe 'selectors', -> + it 'tokenizes type selectors', -> + {tokens} = grammar.tokenizeLine 'p {}' + expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + + it 'tokenizes the universal selector', -> + {tokens} = grammar.tokenizeLine '*' + expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] + + it 'tokenises combinators', -> + {tokens} = grammar.tokenizeLine 'a > b + * ~ :not(.nah)' + expect(tokens[2]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(tokens[6]).toEqual value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(tokens[10]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + + it 'highlights deprecated combinators', -> + {tokens} = grammar.tokenizeLine '.sooo /deep/ >>>_.>>>' + expect(tokens[3]).toEqual value: '/deep/', scopes: ['source.css', 'invalid.deprecated.combinator.css'] + expect(tokens[5]).toEqual value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css'] + + it 'tokenizes complex selectors', -> + {tokens} = grammar.tokenizeLine '[disabled], [disabled] + p' + expect(tokens[0]).toEqual value: '[', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.begin.bracket.square.css"] + expect(tokens[1]).toEqual value: 'disabled', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "entity.other.attribute-name.css"] + expect(tokens[2]).toEqual value: ']', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.end.bracket.square.css"] + expect(tokens[3]).toEqual value: ',', scopes: ["source.css", "meta.selector.css", "punctuation.separator.list.comma.css"] + expect(tokens[5]).toEqual value: '[', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.begin.bracket.square.css"] + expect(tokens[6]).toEqual value: 'disabled', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "entity.other.attribute-name.css"] + expect(tokens[7]).toEqual value: ']', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.end.bracket.square.css"] + expect(tokens[9]).toEqual value: '+', scopes: ["source.css", "meta.selector.css", "keyword.operator.combinator.css"] + expect(tokens[11]).toEqual value: 'p', scopes: ["source.css", "meta.selector.css", "entity.name.tag.css"] + + lines = grammar.tokenizeLines """ + [disabled]:not(:first-child)::before:hover + ~ div.object + + #id.thing:hover > strong ~ p::before, + a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], + *>em.i.ly[data-name|="Life"] { } + """ + expect(lines[0][0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(lines[0][1]).toEqual value: 'disabled', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(lines[0][2]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(lines[0][3]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[0][4]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[0][5]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[0][6]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[0][7]).toEqual value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[0][8]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[0][9]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(lines[0][10]).toEqual value: 'before', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + expect(lines[0][11]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[0][12]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[1][1]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(lines[1][3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[1][4]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(lines[1][5]).toEqual value: 'object', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(lines[2][1]).toEqual value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(lines[2][3]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(lines[2][4]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + expect(lines[2][5]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(lines[2][6]).toEqual value: 'thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(lines[2][7]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[2][8]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[2][10]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(lines[2][12]).toEqual value: 'strong', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[2][14]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(lines[2][16]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[2][17]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(lines[2][18]).toEqual value: 'before', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + expect(lines[2][19]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] + expect(lines[3][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[3][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'invalid.illegal.colon.css'] + expect(lines[3][3]).toEqual value: 'last-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[3][4]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] + expect(lines[3][5]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[3][6]).toEqual value: 'Comment', scopes: ['source.css', 'comment.block.css'] + expect(lines[3][7]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[3][8]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(lines[3][9]).toEqual value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + expect(lines[3][11]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(lines[3][13]).toEqual value: 'html', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[3][14]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(lines[3][15]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(lines[3][16]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(lines[3][17]).toEqual value: 'en-AU', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(lines[3][18]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(lines[3][19]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] + expect(lines[4][0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] + expect(lines[4][1]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(lines[4][2]).toEqual value: 'em', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[4][3]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(lines[4][4]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(lines[4][5]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(lines[4][6]).toEqual value: 'ly', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(lines[4][7]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(lines[4][8]).toEqual value: 'data-name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(lines[4][9]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(lines[4][10]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[4][11]).toEqual value: 'Life', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(lines[4][12]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[4][13]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(lines[4][15]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[4][17]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'custom elements (as type selectors)', -> + it 'only tokenizes identifiers beginning with [a-z]', -> + {tokens} = grammar.tokenizeLine 'pearl-1941 1941-pearl -pearl-1941' + expect(tokens[0]).toEqual value: 'pearl-1941', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + expect(tokens[1]).toEqual value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css'] + + it 'tokenizes custom elements containing non-ASCII letters', -> + {tokens} = grammar.tokenizeLine 'pokémon-ピカチュウ' + expect(tokens[0]).toEqual value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + + it 'does not tokenize identifiers containing [A-Z]', -> + {tokens} = grammar.tokenizeLine 'Basecamp-schedule basecamp-Schedule' + expect(tokens[0]).toEqual value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css'] + + it 'does not tokenize identifiers containing no hyphens', -> + {tokens} = grammar.tokenizeLine 'halo_night' + expect(tokens[0]).toEqual value: 'halo_night', scopes: ['source.css', 'meta.selector.css'] + + it 'does not tokenise identifiers following an @ symbol', -> + {tokens} = grammar.tokenizeLine('@some-weird-new-feature') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + + it 'does not tokenise identifiers in unfamiliar functions', -> + {tokens} = grammar.tokenizeLine('some-edgy-new-function()') + expect(tokens[0]).toEqual value: 'some-edgy-new-function(', scopes: ['source.css', 'meta.selector.css'] + expect(tokens[1]).toEqual value: ')', scopes: ['source.css'] + + describe 'attribute selectors', -> + it 'tokenizes attribute selectors without values', -> + {tokens} = grammar.tokenizeLine '[title]' + expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[1]).toEqual value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[2]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenizes attribute selectors with identifier values', -> + {tokens} = grammar.tokenizeLine '[hreflang|=fr]' + expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[1]).toEqual value: 'hreflang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[2]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[3]).toEqual value: 'fr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[4]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenizes attribute selectors with string values', -> + {tokens} = grammar.tokenizeLine '[href^="http://www.w3.org/"]' + expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[1]).toEqual value: 'href', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[2]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[4]).toEqual value: 'http://www.w3.org/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenizes CSS qualified attribute names with wildcard prefix', -> + {tokens} = grammar.tokenizeLine '[*|title]' + expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[1]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] + expect(tokens[3]).toEqual value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[4]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenizes CSS qualified attribute names with namespace prefix', -> + {tokens} = grammar.tokenizeLine '[marvel|origin=radiation]' + expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[1]).toEqual value: 'marvel', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] + expect(tokens[3]).toEqual value: 'origin', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[4]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[5]).toEqual value: 'radiation', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenizes CSS qualified attribute names without namespace prefix', -> + {tokens} = grammar.tokenizeLine '[|data-hp="75"]' + expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] + expect(tokens[2]).toEqual value: 'data-hp', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[5]).toEqual value: '75', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenises compound ID/attribute selectors', -> + {tokens} = grammar.tokenizeLine('#div[id="0"]{ }') + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + expect(tokens[2]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[3]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[8]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + {tokens} = grammar.tokenizeLine('.bar#div[id="0"]') + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'bar', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[2]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + expect(tokens[4]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[5]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + + it 'tokenises compound class/attribute selectors', -> + {tokens} = grammar.tokenizeLine('.div[id="0"]{ }') + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[2]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[3]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[8]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + {tokens} = grammar.tokenizeLine('#bar.div[id]') + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'bar', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + expect(tokens[2]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[4]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[5]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'allows whitespace to be inserted between tokens', -> + {tokens} = grammar.tokenizeLine('span[ er|lang |= "%%" ]') + expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[3]).toEqual value: 'er', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[4]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] + expect(tokens[5]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[7]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[10]).toEqual value: '%%', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(tokens[11]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[12]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[13]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenises escape sequences inside attribute selectors', -> + {tokens} = grammar.tokenizeLine('a[name\\[0\\]="value"]') + expect(tokens[2]).toEqual value: 'name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[3]).toEqual value: '\\[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] + expect(tokens[4]).toEqual value: '0', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[5]).toEqual value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] + expect(tokens[6]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[10]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenises escape sequences inside namespace prefixes', -> + {tokens} = grammar.tokenizeLine('a[name\\ space|Get\\ It\\?="kek"]') + expect(tokens[2]).toEqual value: 'name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[3]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css', 'constant.character.escape.css'] + expect(tokens[4]).toEqual value: 'space', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[5]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] + expect(tokens[6]).toEqual value: 'Get', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[7]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] + expect(tokens[8]).toEqual value: 'It', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[9]).toEqual value: '\\?', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] + expect(tokens[10]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[14]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenises comments inside attribute selectors', -> + {tokens} = grammar.tokenizeLine('span[/*]*/lang]') + expect(tokens[0]).toEqual value: 'span', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[5]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenises quoted strings in attribute selectors', -> + {tokens} = grammar.tokenizeLine('a[href^="#"] a[href^= "#"] a[href^="#" ]') + expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[5]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[12]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[13]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[14]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[15]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(tokens[16]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[23]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[24]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(tokens[25]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[26]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[27]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + {tokens} = grammar.tokenizeLine("a[href^='#'] a[href^= '#'] a[href^='#' ]") + expect(tokens[4]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[5]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] + expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + expect(tokens[12]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[13]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[14]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[15]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] + expect(tokens[16]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + expect(tokens[23]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[24]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] + expect(tokens[25]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + expect(tokens[26]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[27]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenises unquoted strings in attribute selectors', -> + {tokens} = grammar.tokenizeLine('span[class~=Java]') + expect(tokens[3]).toEqual value: '~=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[4]).toEqual value: 'Java', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[5]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + {tokens} = grammar.tokenizeLine('span[class^= 0xDEADCAFE=|~BEEFBABE ]') + expect(tokens[3]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[4]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[5]).toEqual value: '0xDEADCAFE=|~BEEFBABE', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenises escape sequences in unquoted strings', -> + {tokens} = grammar.tokenizeLine('a[name\\[0\\]=a\\BAD\\AF\\]a\\ i] {}') + expect(tokens[6]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[7]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[8]).toEqual value: '\\BAD', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.codepoint.css'] + expect(tokens[9]).toEqual value: '\\AF', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.codepoint.css'] + expect(tokens[10]).toEqual value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css'] + expect(tokens[11]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[12]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css'] + expect(tokens[13]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[14]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(tokens[16]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'tokenises the ignore-case modifier at the end of a selector', -> + {tokens} = grammar.tokenizeLine('a[attr=val i] a[attr="val" i] a[attr=\'val\'I] a[val^= \'"\'i] a[attr= i] a[attr= i i]') + expect(tokens[6]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] + expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(tokens[16]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[17]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] + expect(tokens[26]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + expect(tokens[27]).toEqual value: 'I', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] + expect(tokens[28]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(tokens[34]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[35]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[36]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] + expect(tokens[37]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + expect(tokens[38]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] + expect(tokens[39]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(tokens[44]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[45]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[46]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[47]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(tokens[52]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(tokens[53]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[54]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] + expect(tokens[55]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(tokens[56]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] + expect(tokens[57]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + it 'tokenises attribute selectors spanning multiple lines', -> + lines = grammar.tokenizeLines """ + span[ + \\x20{2} + ns|lang/**/ + |= + "pt"] + """ + expect(lines[0][0]).toEqual value: 'span', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[0][1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(lines[1][0]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] + expect(lines[2][1]).toEqual value: 'ns', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] + expect(lines[2][2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] + expect(lines[2][3]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][5]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[3][1]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(lines[4][0]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[4][1]).toEqual value: 'pt', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(lines[4][2]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[4][3]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + lines = grammar.tokenizeLines """ + span[/*=== + ==|span[/*} + ====*/*|lang/*]=*/~=/*"|"*/"en-AU"/* + | + */ + i] + """ + expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][3]).toEqual value: '===', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] + expect(lines[1][0]).toEqual value: '==|span[/*}', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] + expect(lines[2][0]).toEqual value: '====', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] + expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] + expect(lines[2][3]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] + expect(lines[2][4]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(lines[2][5]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][6]).toEqual value: ']=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] + expect(lines[2][7]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][8]).toEqual value: '~=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(lines[2][9]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][10]).toEqual value: '"|"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] + expect(lines[2][11]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][12]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[2][13]).toEqual value: 'en-AU', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(lines[2][14]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[2][15]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[3][0]).toEqual value: ' |', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] + expect(lines[4][0]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[5][0]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] + expect(lines[5][1]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + + describe 'class selectors', -> + it 'tokenizes class selectors containing non-ASCII letters', -> + {tokens} = grammar.tokenizeLine '.étendard' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'étendard', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + + {tokens} = grammar.tokenizeLine '.スポンサー' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + + it 'tokenizes a class selector consisting of two hypens', -> + {tokens} = grammar.tokenizeLine '.--' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + + it 'tokenizes class selectors consisting of one (valid) character', -> + {tokens} = grammar.tokenizeLine '._' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + + it 'tokenises class selectors starting with an escape sequence', -> + {tokens} = grammar.tokenizeLine '.\\33\\44-model {' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css'] + expect(tokens[2]).toEqual value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css'] + expect(tokens[3]).toEqual value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'tokenises class selectors ending with an escape sequence', -> + {tokens} = grammar.tokenizeLine '.la\\{tex\\} {' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css'] + expect(tokens[3]).toEqual value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[4]).toEqual value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css'] + expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'marks a class invalid if it contains unescaped ASCII punctuation or symbols other than "-" and "_"', -> + {tokens} = grammar.tokenizeLine '.B&W{' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'B&W', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'marks a class invalid if it starts with ASCII digits ([0-9])', -> + {tokens} = grammar.tokenizeLine '.666{' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'marks a class invalid if it starts with "-" followed by ASCII digits', -> + {tokens} = grammar.tokenizeLine '.-911-{' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'marks a class invalid if it consists of only one hyphen', -> + {tokens} = grammar.tokenizeLine '.-{' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + describe 'id selectors', -> + it 'tokenizes id selectors consisting of ASCII letters', -> + {tokens} = grammar.tokenizeLine '#unicorn' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + + it 'tokenizes id selectors containing non-ASCII letters', -> + {tokens} = grammar.tokenizeLine '#洪荒之力' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + + it 'tokenizes id selectors containing [0-9], "-", or "_"', -> + {tokens} = grammar.tokenizeLine '#_zer0-day' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + + it 'tokenizes id selectors beginning with two hyphens', -> + {tokens} = grammar.tokenizeLine '#--d3bug--' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + + it 'marks an id invalid if it contains ASCII punctuation or symbols other than "-" and "_"', -> + {tokens} = grammar.tokenizeLine '#sort!{' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'sort!', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'marks an id invalid if it starts with ASCII digits ([0-9])', -> + {tokens} = grammar.tokenizeLine '#666{' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'marks an id invalid if it starts with "-" followed by ASCII digits', -> + {tokens} = grammar.tokenizeLine '#-911-{' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'marks an id invalid if it consists of one hyphen only', -> + {tokens} = grammar.tokenizeLine '#-{' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'tokenises ID selectors starting with an escape sequence', -> + {tokens} = grammar.tokenizeLine '#\\33\\44-model {' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css'] + expect(tokens[2]).toEqual value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css'] + expect(tokens[3]).toEqual value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'tokenises ID selectors ending with an escape sequence', -> + {tokens} = grammar.tokenizeLine '#la\\{tex\\} {' + expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css'] + expect(tokens[3]).toEqual value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + expect(tokens[4]).toEqual value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css'] + expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + describe 'namespace prefixes', -> + it 'tokenises arbitrary namespace prefixes', -> + {tokens} = grammar.tokenizeLine('foo|h1 { }') + expect(tokens[0]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] + expect(tokens[2]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenises anonymous namespace prefixes', -> + {tokens} = grammar.tokenizeLine('*|abbr {}') + expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] + expect(tokens[2]).toEqual value: 'abbr', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('*|* {}') + expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] + expect(tokens[2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] + expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('foo|* { }') + expect(tokens[0]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] + expect(tokens[2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] + expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('|[svg|attr=name]{}') + expect(tokens[0]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] + expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(tokens[2]).toEqual value: 'svg', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] + expect(tokens[3]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] + expect(tokens[4]).toEqual value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + + it 'tokenises the "no-namespace" prefix', -> + {tokens} = grammar.tokenizeLine('|h1 { }') + expect(tokens[0]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] + expect(tokens[1]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it "doesn't tokenise prefixes without a selector", -> + {tokens} = grammar.tokenizeLine('*| { }') + expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] + expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('*|{ }') + expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] + expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'at-rules', -> + describe '@charset', -> + # NB: \A won't match if "tokenizeLine" is used; "tokenizeLines" is used here to circumvent this limitation + it 'tokenises @charset rules at the start of a file', -> + lines = grammar.tokenizeLines '@charset "US-ASCII";' + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] + expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] + expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[0][4]).toEqual value: 'US-ASCII', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] + expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[0][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] + + lines = grammar.tokenizeLines('/* Not the first line */\n@charset "UTF-8";') + expect(lines[0][0]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][1]).toEqual value: ' Not the first line ', scopes: ['source.css', 'comment.block.css'] + expect(lines[0][2]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] + expect(lines[1][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + + it 'highlights invalid @charset statements', -> + lines = grammar.tokenizeLines " @charset 'US-ASCII';" + expect(lines[0][0]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.leading-whitespace.charset.css'] + expect(lines[0][1]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] + expect(lines[0][2]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] + expect(lines[0][4]).toEqual value: "'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-double-quoted.charset.css'] + expect(lines[0][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] + + lines = grammar.tokenizeLines '@charset "iso-8859-15";' + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] + expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.whitespace.charset.css'] + expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[0][4]).toEqual value: 'iso-8859-15', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] + expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[0][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] + + lines = grammar.tokenizeLines '@charset"US-ASCII";' + expect(lines[0][0]).toEqual value: '@charset"US-ASCII"', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.no-whitespace.charset.css'] + expect(lines[0][1]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] + + lines = grammar.tokenizeLines '@charset "UTF-8" ;' + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] + expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] + expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[0][4]).toEqual value: 'UTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] + expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unexpected-characters.charset.css'] + expect(lines[0][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] + + lines = grammar.tokenizeLines '@charset "WTF-8" /* Nope */ ;' + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] + expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] + expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[0][4]).toEqual value: 'WTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] + expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[0][6]).toEqual value: ' /* Nope */ ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unexpected-characters.charset.css'] + expect(lines[0][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] + + lines = grammar.tokenizeLines '@charset "UTF-8' + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] + expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] + expect(lines[0][3]).toEqual value: '"UTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unclosed-string.charset.css'] + + lines = grammar.tokenizeLines "@CHARSET 'US-ASCII';" + expect(lines[0][0]).toEqual value: '@CHARSET', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-lowercase.charset.css'] + expect(lines[0][1]).toEqual value: " 'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css'] + expect(lines[0][2]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] + + describe '@import', -> + it 'tokenises @import statements', -> + {tokens} = grammar.tokenizeLine('@import url("file.css");') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[6]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine('@import "file.css";') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[4]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine("@import 'file.css';") + expect(tokens[3]).toEqual value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[4]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css'] + expect(tokens[5]).toEqual value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + + it "doesn't let injected comments impact parameter matching", -> + {tokens} = grammar.tokenizeLine('@import /* url("name"); */ "1.css";') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[4]).toEqual value: ' url("name"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] + expect(tokens[5]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[8]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] + expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine('@import/* Comment */"2.css";') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: ' Comment ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[6]).toEqual value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + it 'correctly handles word boundaries', -> + {tokens} = grammar.tokenizeLine('@import"file.css";') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[3]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] + expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine('@import-file.css;') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import-file', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + expect(tokens[2]).toEqual value: '.css', scopes: ['source.css', 'meta.at-rule.header.css'] + expect(tokens[3]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css'] + + it 'matches a URL that starts on the next line', -> + lines = grammar.tokenizeLines '@import\nurl("file.css");' + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(lines[0][2]).toEqual value: '', scopes: ['source.css', 'meta.at-rule.import.css'] + expect(lines[1][0]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] + expect(lines[1][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[1][3]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] + expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[1][5]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[1][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + it 'matches comments inside query lists', -> + {tokens} = grammar.tokenizeLine('@import url("1.css") print /* url(";"); */ all;') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[6]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[10]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] + expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[13]).toEqual value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] + expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[16]).toEqual value: 'all', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] + expect(tokens[17]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + it 'highlights deprecated media types', -> + {tokens} = grammar.tokenizeLine('@import "astral.css" projection;') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[4]).toEqual value: 'astral.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[7]).toEqual value: 'projection', scopes: ['source.css', 'meta.at-rule.import.css', 'invalid.deprecated.constant.media.css'] + expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + it 'highlights media features in query lists', -> + {tokens} = grammar.tokenizeLine('@import url(\'landscape.css\') screen and (orientation:landscape);') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[5]).toEqual value: '\'', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[6]).toEqual value: 'landscape.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css'] + expect(tokens[7]).toEqual value: '\'', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] + expect(tokens[12]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.operator.logical.and.media.css'] + expect(tokens[14]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[15]).toEqual value: 'orientation', scopes: ['source.css', 'meta.at-rule.import.css', 'support.type.property-name.media.css'] + expect(tokens[16]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.separator.key-value.css'] + expect(tokens[17]).toEqual value: 'landscape', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.property-value.css'] + expect(tokens[18]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[19]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + describe '@media', -> + it 'tokenises @media keywords correctly', -> + {tokens} = grammar.tokenizeLine('@media(max-width: 37.5em) { }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[3]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(tokens[7]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[9]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('@media not print and (max-width: 37.5em){ }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.not.media.css'] + expect(tokens[5]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(tokens[7]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] + expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[10]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(tokens[11]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[13]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(tokens[14]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[16]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[18]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + it 'highlights deprecated media types', -> + {tokens} = grammar.tokenizeLine('@media (max-device-width: 2px){ }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: 'max-device-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + it 'highlights vendored media features', -> + {tokens} = grammar.tokenizeLine('@media (-webkit-foo: bar){ b{ } }') + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: '-webkit-foo', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: ' bar', scopes: ['source.css', 'meta.at-rule.media.header.css'] + expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[8]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('@media screen and (-ms-high-contrast:black-on-white){ }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(tokens[5]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: '-ms-high-contrast', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] + expect(tokens[9]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[10]).toEqual value: 'black-on-white', scopes: ['source.css', 'meta.at-rule.media.header.css'] + expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('@media (_moz-a:b){}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: '_moz-a', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: 'b', scopes: ['source.css', 'meta.at-rule.media.header.css'] + expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + + {tokens} = grammar.tokenizeLine('@media (-hp-foo:bar){}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: '-hp-foo', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: 'bar', scopes: ['source.css', 'meta.at-rule.media.header.css'] + expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + + {tokens} = grammar.tokenizeLine('@media (mso-page-size:wide){}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: 'mso-page-size', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: 'wide', scopes: ['source.css', 'meta.at-rule.media.header.css'] + expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + + it 'tokenises @media immediately following a closing brace', -> + {tokens} = grammar.tokenizeLine('h1 { }@media only screen { } h2 { }') + expect(tokens[0]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(tokens[5]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[6]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[8]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] + expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + expect(tokens[16]).toEqual value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[18]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[20]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('h1 { }@media only screen { }h2 { }') + expect(tokens[0]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(tokens[5]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[6]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[8]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] + expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + expect(tokens[15]).toEqual value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[17]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[19]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenises level 4 media-query syntax', -> + lines = grammar.tokenizeLines """ + @media (min-width >= 0px) + and (max-width <= 400) + and (min-height > 400) + and (max-height < 200) + """ + expect(lines[0][6]).toEqual value: '>=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] + expect(lines[1][6]).toEqual value: '<=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] + expect(lines[2][6]).toEqual value: '>', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] + expect(lines[3][6]).toEqual value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] + + it 'tokenises comments between media types', -> + {tokens} = grammar.tokenizeLine('@media/* */only/* */screen/* */and (min-width:1100px){}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[5]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] + expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[9]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(tokens[10]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[12]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[13]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] + expect(tokens[15]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[16]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(tokens[17]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[18]).toEqual value: '1100', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(tokens[19]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[20]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[21]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[22]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + it 'tokenises comments between media features', -> + {tokens} = grammar.tokenizeLine('@media/*=*/(max-width:/**/37.5em)/*=*/and/*=*/(/*=*/min-height/*:*/:/*=*/1.2em/*;*/){}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[6]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[10]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(tokens[11]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[13]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[14]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[15]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[16]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] + expect(tokens[17]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[18]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[19]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[20]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[21]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[22]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[23]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[24]).toEqual value: 'min-height', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(tokens[25]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[26]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[27]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[28]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[29]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[30]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[31]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[32]).toEqual value: '1.2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(tokens[33]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(tokens[34]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[35]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[36]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[37]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(tokens[38]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[39]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + it 'matches media queries across lines', -> + lines = grammar.tokenizeLines """ + @media only screen and (min-width : /* 40 */ + 320px), + not print and (max-width: 480px) /* kek */ and (-webkit-min-device-pixel-ratio /*:*/ : 2), + only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-ratio: 2) { } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(lines[0][3]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] + expect(lines[0][5]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(lines[0][7]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] + expect(lines[0][9]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(lines[0][10]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(lines[0][12]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(lines[0][14]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][15]).toEqual value: ' 40 ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(lines[0][16]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[1][1]).toEqual value: '320', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(lines[1][2]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[1][3]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(lines[1][4]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] + expect(lines[2][1]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.not.media.css'] + expect(lines[2][3]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(lines[2][5]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] + expect(lines[2][7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(lines[2][8]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(lines[2][9]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(lines[2][11]).toEqual value: '480', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(lines[2][12]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[2][13]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(lines[2][15]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][16]).toEqual value: ' kek ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(lines[2][17]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][19]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] + expect(lines[2][21]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(lines[2][22]).toEqual value: '-webkit-min-device-pixel-ratio', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] + expect(lines[2][24]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][25]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(lines[2][26]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][28]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(lines[2][30]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(lines[2][31]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(lines[2][32]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] + expect(lines[3][0]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] + expect(lines[3][2]).toEqual value: 'speech', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(lines[3][4]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] + expect(lines[3][6]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(lines[3][7]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(lines[3][8]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(lines[3][10]).toEqual value: '10', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(lines[3][11]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[3][12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(lines[3][13]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] + expect(lines[3][15]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[3][16]).toEqual value: ' wat ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(lines[3][17]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[3][19]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(lines[3][20]).toEqual value: '-webkit-min-device-pixel-ratio', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] + expect(lines[3][21]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(lines[3][23]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(lines[3][24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + expect(lines[3][26]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(lines[3][28]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + it 'highlights invalid commas', -> + {tokens} = grammar.tokenizeLine('@media , {}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css'] + expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('@media , ,screen {}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: ', ,', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css'] + expect(tokens[4]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] + expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] + expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] + + it 'allows spaces inside ratio values', -> + {tokens} = grammar.tokenizeLine('@media (min-aspect-ratio: 3 / 4) and (max-aspect-ratio: 20 / 17) {}') + expect(tokens[7]).toEqual value: '3', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] + expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] + expect(tokens[9]).toEqual value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css'] + expect(tokens[10]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] + expect(tokens[11]).toEqual value: '4', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] + expect(tokens[20]).toEqual value: '20', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] + expect(tokens[21]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] + expect(tokens[22]).toEqual value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css'] + expect(tokens[23]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] + expect(tokens[24]).toEqual value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] + + describe '@keyframes', -> + it 'tokenises keyframe lists correctly', -> + lines = grammar.tokenizeLines """ + @keyframes important1 { + from { margin-top: 50px; + margin-bottom: 100px } + 50% { margin-top: 150px !important; } /* Ignored */ + to { margin-top: 100px; } + } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] + expect(lines[0][3]).toEqual value: 'important1', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] + expect(lines[0][4]).toEqual value: ' ', scopes: ['source.css'] + expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] + expect(lines[1][1]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] + expect(lines[1][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[1][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[1][8]).toEqual value: '50', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[1][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[1][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[2][1]).toEqual value: 'margin-bottom', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[2][4]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[2][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[2][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[3][1]).toEqual value: '50%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] + expect(lines[3][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[3][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[3][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[3][8]).toEqual value: '150', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[3][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[3][11]).toEqual value: '!important', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'keyword.other.important.css'] + expect(lines[3][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[3][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[3][16]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[3][17]).toEqual value: ' Ignored ', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css'] + expect(lines[3][18]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[4][1]).toEqual value: 'to', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] + expect(lines[4][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[4][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[4][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[4][8]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[4][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[4][12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[5][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] + + it 'matches injected comments', -> + lines = grammar.tokenizeLines """ + @keyframes/*{*/___IDENT__/*} + { Nah { margin-top: 2em; } + */{ from + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] + expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] + expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[0][5]).toEqual value: '___IDENT__', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] + expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] + expect(lines[1][0]).toEqual value: ' { Nah { margin-top: 2em; }', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] + expect(lines[2][0]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][1]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] + expect(lines[2][3]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] + + it 'matches offset keywords case-insensitively', -> + {tokens} = grammar.tokenizeLine('@keyframes Give-them-both { fROm { } To {} }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] + expect(tokens[3]).toEqual value: 'Give-them-both', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] + expect(tokens[4]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] + expect(tokens[7]).toEqual value: 'fROm', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] + expect(tokens[9]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[11]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(tokens[13]).toEqual value: 'To', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] + expect(tokens[15]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[16]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(tokens[18]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] + + it 'matches percentile offsets', -> + {tokens} = grammar.tokenizeLine('@keyframes identifier { -50.2% } @keyframes ident2 { .25%}') + expect(tokens[7]).toEqual value: '-50.2%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] + expect(tokens[18]).toEqual value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] + + it 'highlights escape sequences inside identifiers', -> + {tokens} = grammar.tokenizeLine '@keyframes A\\1F602Z' + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] + expect(tokens[3]).toEqual value: 'A', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] + expect(tokens[4]).toEqual value: '\\1F602', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css', 'constant.character.escape.codepoint.css'] + expect(tokens[5]).toEqual value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] + + describe '@supports', -> + it 'tokenises feature queries', -> + {tokens} = grammar.tokenizeLine('@supports (font-size: 1em) { }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.supports.header.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: 'font-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(tokens[7]).toEqual value: '1', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[8]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(tokens[10]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[11]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] + expect(tokens[13]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] + + it 'matches logical operators', -> + lines = grammar.tokenizeLines """ + @supports not (font-size: 1em){ } + @supports (font-size: 1em) and (font-size: 1em){ } + @supports (font-size: 1em) or (font-size: 1em){ } + """ + expect(lines[0][3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] + expect(lines[1][11]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css'] + expect(lines[2][11]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] + + it 'matches custom variables in feature queries', -> + {tokens} = grammar.tokenizeLine('@supports (--foo: green){}') + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: '--foo', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'variable.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(tokens[7]).toEqual value: 'green', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + + it "doesn't mistake brackets in string literals for feature queries", -> + lines = grammar.tokenizeLines """ + @supports not ((tab-size:4) or (-moz-tab-size:4)){ + body::before{content: "Come on, Microsoft (Get it together already)…"; } + } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] + expect(lines[0][3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] + expect(lines[0][7]).toEqual value: 'tab-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[0][12]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'keyword.operator.logical.feature.or.css'] + expect(lines[0][15]).toEqual value: '-moz-tab-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] + expect(lines[0][20]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] + expect(lines[1][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[1][2]).toEqual value: '::', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(lines[1][3]).toEqual value: 'before', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + expect(lines[1][4]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[1][5]).toEqual value: 'content', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[1][8]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[1][9]).toEqual value: 'Come on, Microsoft (Get it together already)…', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] + expect(lines[1][10]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[1][11]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[1][13]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[2][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] + + it 'tokenises multiple feature queries', -> + {tokens} = grammar.tokenizeLine('@supports (display:table-cell) or ((display:list-item) and (display:run-in)){') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: 'table-cell', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(tokens[9]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] + expect(tokens[11]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(tokens[12]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(tokens[13]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[14]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(tokens[15]).toEqual value: 'list-item', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[16]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(tokens[18]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'keyword.operator.logical.feature.and.css'] + expect(tokens[20]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(tokens[21]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[22]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(tokens[23]).toEqual value: 'run-in', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(tokens[25]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(tokens[26]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] + + it 'embeds rulesets and other at-rules', -> + lines = grammar.tokenizeLines """ + @supports (animation-name: test) { + #node { + animation-name: test; + } + body > header[data-name="attr"] ~ *:not(:first-child){ + content: "😂👌" + } + @keyframes important1 { + from { + margin-top: 50px; + margin-bottom: 100px + } + 50% { margin-top: 150px !important; } /* Ignored */ + to { margin-top: 100px; } + } + } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] + expect(lines[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(lines[0][4]).toEqual value: 'animation-name', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(lines[0][7]).toEqual value: 'test', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css'] + expect(lines[0][8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(lines[0][10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] + expect(lines[1][1]).toEqual value: '#', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] + expect(lines[1][2]).toEqual value: 'node', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] + expect(lines[1][4]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[2][1]).toEqual value: 'animation-name', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[2][4]).toEqual value: 'test', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(lines[2][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[3][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[4][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[4][3]).toEqual value: '>', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(lines[4][5]).toEqual value: 'header', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[4][6]).toEqual value: '[', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] + expect(lines[4][7]).toEqual value: 'data-name', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] + expect(lines[4][8]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] + expect(lines[4][9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[4][10]).toEqual value: 'attr', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] + expect(lines[4][11]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[4][12]).toEqual value: ']', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] + expect(lines[4][14]).toEqual value: '~', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'keyword.operator.combinator.css'] + expect(lines[4][16]).toEqual value: '*', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] + expect(lines[4][17]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[4][18]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[4][19]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[4][20]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[4][21]).toEqual value: 'first-child', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[4][22]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[4][23]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[5][1]).toEqual value: 'content', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[5][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[5][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[5][5]).toEqual value: '😂👌', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] + expect(lines[5][6]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[6][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[7][1]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] + expect(lines[7][2]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] + expect(lines[7][4]).toEqual value: 'important1', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] + expect(lines[7][6]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] + expect(lines[8][1]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] + expect(lines[8][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[9][1]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[9][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[9][4]).toEqual value: '50', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[9][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[9][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[10][1]).toEqual value: 'margin-bottom', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[10][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[10][4]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[10][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[11][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[12][1]).toEqual value: '50%', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] + expect(lines[12][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[12][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[12][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[12][8]).toEqual value: '150', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[12][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[12][11]).toEqual value: '!important', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'keyword.other.important.css'] + expect(lines[12][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[12][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[12][16]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[12][17]).toEqual value: ' Ignored ', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css'] + expect(lines[12][18]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[13][1]).toEqual value: 'to', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] + expect(lines[13][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[13][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[13][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[13][8]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[13][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[13][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[13][12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[14][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] + expect(lines[15][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] + + it 'matches injected comments', -> + # NB: This particular example actually isn't valid @supports + # syntax; it's just for stress-testing boundary-matching. + lines = grammar.tokenizeLines """ + @supports/*===*/not/*==****************| + ==*/(display:table-cell)/*============*/ and (display: list-item)/*}*/{} + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] + expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][3]).toEqual value: '===', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] + expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[0][5]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] + expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][7]).toEqual value: '==****************|', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] + expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] + expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[1][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(lines[1][3]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[1][4]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(lines[1][5]).toEqual value: 'table-cell', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[1][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(lines[1][7]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[1][8]).toEqual value: '============', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] + expect(lines[1][9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[1][11]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css'] + expect(lines[1][13]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(lines[1][19]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[1][20]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] + expect(lines[1][21]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[1][22]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] + expect(lines[1][23]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] + + it 'matches feature queries across multiple lines', -> + lines = grammar.tokenizeLines """ + @supports + (box-shadow: 0 0 2px rgba(0,0,0,.5) inset) or + (-moz-box-shadow: 0 0 2px black inset) or + (-webkit-box-shadow: 0 0 2px black inset) or + (-o-box-shadow: 0 0 2px black inset) + { .noticebox { } } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] + expect(lines[1][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(lines[1][2]).toEqual value: 'box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[1][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(lines[1][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[1][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[1][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[1][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[1][12]).toEqual value: 'rgba', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[1][13]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][14]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[1][15]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(lines[1][16]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[1][17]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(lines[1][18]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[1][19]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(lines[1][20]).toEqual value: '.5', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[1][21]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[1][23]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[1][24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(lines[1][26]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] + expect(lines[2][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(lines[2][2]).toEqual value: '-moz-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] + expect(lines[2][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(lines[2][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[2][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[2][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[2][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[2][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(lines[2][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[2][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(lines[2][17]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] + expect(lines[3][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(lines[3][2]).toEqual value: '-webkit-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] + expect(lines[3][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(lines[3][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[3][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[3][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[3][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[3][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(lines[3][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[3][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(lines[3][17]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] + expect(lines[4][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] + expect(lines[4][2]).toEqual value: '-o-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] + expect(lines[4][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] + expect(lines[4][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[4][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(lines[4][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[4][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] + expect(lines[5][0]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] + expect(lines[5][2]).toEqual value: '.', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(lines[5][3]).toEqual value: 'noticebox', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(lines[5][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[5][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[5][9]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] + + describe '@namespace', -> + it 'tokenises @namespace statements correctly', -> + {tokens} = grammar.tokenizeLine('@namespace "XML";') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[4]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine('@namespace prefix "XML" ;') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] + expect(tokens[3]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] + expect(tokens[4]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[6]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] + expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine('@namespace url("http://a.bc/");') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] + expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[6]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] + + it "doesn't confuse a prefix of 'url' as a function", -> + {tokens} = grammar.tokenizeLine('@namespace url url("http://a.bc/");') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] + expect(tokens[5]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] + expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[8]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] + expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[11]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] + + it 'permits injected comments between tokens', -> + {tokens} = grammar.tokenizeLine('@namespace/*=*/pre/*=*/"url"/*=*/;') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[5]).toEqual value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] + expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[7]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] + expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[10]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] + expect(tokens[11]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[13]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] + expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] + + it 'allows no spaces between "@namespace" and quoted URLs', -> + {tokens} = grammar.tokenizeLine('@namespace"XML";') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[3]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] + expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] + + it 'tokenises escape sequences in prefixes', -> + {tokens} = grammar.tokenizeLine('@namespace pre\\ fix "http://url/";') + expect(tokens[3]).toEqual value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] + expect(tokens[4]).toEqual value: '\\ ', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css', 'constant.character.escape.css'] + expect(tokens[5]).toEqual value: 'fix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + + it 'allows arguments to span multiple lines', -> + lines = grammar.tokenizeLines """ + @namespace + prefix"XML"; + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(lines[1][0]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] + expect(lines[1][1]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[1][2]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] + expect(lines[1][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[1][4]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] + + lines = grammar.tokenizeLines """ + @namespace + + prefix + + url("http://a.bc/"); + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(lines[2][1]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] + expect(lines[4][0]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] + expect(lines[4][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[4][2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[4][3]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] + expect(lines[4][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[4][5]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[4][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] + + describe 'font-feature declarations', -> + it 'tokenises font-feature blocks', -> + {tokens} = grammar.tokenizeLine('@font-feature-values Font name 2 { }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.font-features.css'] + expect(tokens[3]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] + expect(tokens[4]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'allows font-feature names to start on a different line', -> + lines = grammar.tokenizeLines """ + @font-feature-values + Font name 2 + { + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] + expect(lines[1][0]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] + expect(lines[2][0]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'matches injected comments', -> + {tokens} = grammar.tokenizeLine('@font-feature-values/*{*/Font/*}*/name/*{*/2{') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[5]).toEqual value: 'Font', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] + expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] + expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[9]).toEqual value: 'name', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] + expect(tokens[10]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[11]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] + expect(tokens[12]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[13]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] + expect(tokens[14]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'tokenises at-rules for feature names', -> + lines = grammar.tokenizeLines """ + @swash{ swashy: 2; } + @ornaments{ ident: 2; } + @annotation{ ident: 1; } + @stylistic{ stylish: 2; } + @styleset{ sets: 2 3 4; } + @character-variant{ charvar: 2 } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] + expect(lines[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[0][4]).toEqual value: 'swashy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(lines[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] + expect(lines[0][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[0][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] + expect(lines[0][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css', 'punctuation.definition.keyword.css'] + expect(lines[1][1]).toEqual value: 'ornaments', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css'] + expect(lines[1][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[1][4]).toEqual value: 'ident', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(lines[1][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] + expect(lines[1][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[1][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] + expect(lines[1][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[2][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css', 'punctuation.definition.keyword.css'] + expect(lines[2][1]).toEqual value: 'annotation', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css'] + expect(lines[2][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[2][4]).toEqual value: 'ident', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(lines[2][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] + expect(lines[2][7]).toEqual value: '1', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[2][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] + expect(lines[2][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[3][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css', 'punctuation.definition.keyword.css'] + expect(lines[3][1]).toEqual value: 'stylistic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css'] + expect(lines[3][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[3][4]).toEqual value: 'stylish', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(lines[3][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] + expect(lines[3][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[3][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] + expect(lines[3][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[4][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css', 'punctuation.definition.keyword.css'] + expect(lines[4][1]).toEqual value: 'styleset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css'] + expect(lines[4][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[4][4]).toEqual value: 'sets', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(lines[4][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] + expect(lines[4][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][9]).toEqual value: '3', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][11]).toEqual value: '4', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] + expect(lines[4][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[5][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css', 'punctuation.definition.keyword.css'] + expect(lines[5][1]).toEqual value: 'character-variant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css'] + expect(lines[5][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[5][4]).toEqual value: 'charvar', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(lines[5][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] + expect(lines[5][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[5][9]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'matches feature-name rules case-insensitively', -> + lines = grammar.tokenizeLines """ + @sWASH{ swashy: 2; } + @ornaMENts{ ident: 2; } + @anNOTatION{ ident: 1; } + @styLISTic{ stylish: 2; } + @STYLEset{ sets: 2 3 4; } + @CHARacter-VARiant{ charvar: 2 } + """ + expect(lines[0][1]).toEqual value: 'sWASH', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] + expect(lines[1][1]).toEqual value: 'ornaMENts', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css'] + expect(lines[2][1]).toEqual value: 'anNOTatION', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css'] + expect(lines[3][1]).toEqual value: 'styLISTic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css'] + expect(lines[4][1]).toEqual value: 'STYLEset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css'] + expect(lines[5][1]).toEqual value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css'] + + it 'matches comments inside feature-name rules', -> + lines = grammar.tokenizeLines """ + @font-feature-values Font name 2 { + @swash{/* + ========*/swashy:/**/2;/**/} + } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] + expect(lines[0][3]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] + expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] + expect(lines[1][1]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] + expect(lines[1][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[1][3]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][0]).toEqual value: '========', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css'] + expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][2]).toEqual value: 'swashy', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(lines[2][3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] + expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][5]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][6]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[2][7]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] + expect(lines[2][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[3][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'highlights escape sequences inside feature-names', -> + {tokens} = grammar.tokenizeLine('@swash{ s\\000077a\\73hy: 1; }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] + expect(tokens[4]).toEqual value: 's', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(tokens[5]).toEqual value: '\\000077', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css'] + expect(tokens[6]).toEqual value: 'a', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + expect(tokens[7]).toEqual value: '\\73', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css'] + expect(tokens[8]).toEqual value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] + + describe '@page', -> + it 'tokenises @page blocks correctly', -> + {tokens} = grammar.tokenizeLine('@page :first { }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[4]).toEqual value: 'first', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[5]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[8]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('@page:right{}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] + expect(tokens[2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[3]).toEqual value: 'right', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('@page{}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[3]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe '@counter-style', -> + it 'tokenises them and their contents correctly', -> + lines = grammar.tokenizeLines """ + @counter-style winners-list { + system: fixed; + symbols: url(gold-medal.svg) url(silver-medal.svg) url(bronze-medal.svg); + suffix: " "; + } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] + expect(lines[0][3]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] + expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[1][1]).toEqual value: 'system', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] + expect(lines[1][4]).toEqual value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[1][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] + expect(lines[2][1]).toEqual value: 'symbols', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] + expect(lines[2][4]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] + expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][6]).toEqual value: 'gold-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] + expect(lines[2][7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][9]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] + expect(lines[2][10]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][11]).toEqual value: 'silver-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] + expect(lines[2][12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][14]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] + expect(lines[2][15]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][16]).toEqual value: 'bronze-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] + expect(lines[2][17]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][18]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] + expect(lines[3][1]).toEqual value: 'suffix', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] + expect(lines[3][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[3][6]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[3][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] + expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'matches injected comments', -> + {tokens} = grammar.tokenizeLine('@counter-style/*{*/winners-list/*}*/{ system: fixed; }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[5]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] + expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css'] + expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[9]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[11]).toEqual value: 'system', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[12]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] + expect(tokens[14]).toEqual value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] + expect(tokens[17]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it "allows the counter-style's name to start on a different line", -> + lines = grammar.tokenizeLines """ + @counter-style + winners-list + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] + expect(lines[1][0]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] + + it "highlights escape sequences inside the style's name", -> + {tokens} = grammar.tokenizeLine '@counter-style A\\01F602z' + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] + expect(tokens[3]).toEqual value: 'A', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] + expect(tokens[4]).toEqual value: '\\01F602', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css', 'constant.character.escape.codepoint.css'] + expect(tokens[5]).toEqual value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] + + describe '@document', -> + it 'correctly tokenises @document rules', -> + lines = grammar.tokenizeLines """ + @document url(http://www.w3.org/), + url-prefix(http://www.w3.org/Style/), /* Comment */ + domain(/**/mozilla.org), + regexp("https:.*") { + body{ color: #f00; } + } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: 'document', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css'] + expect(lines[0][3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'support.function.url.css'] + expect(lines[0][4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[0][5]).toEqual value: 'http://www.w3.org/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'variable.parameter.url.css'] + expect(lines[0][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[0][7]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] + expect(lines[1][1]).toEqual value: 'url-prefix', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] + expect(lines[1][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][3]).toEqual value: 'http://www.w3.org/Style/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'variable.parameter.document-rule.css'] + expect(lines[1][4]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[1][5]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] + expect(lines[1][7]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[1][8]).toEqual value: ' Comment ', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css'] + expect(lines[1][9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][1]).toEqual value: 'domain', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] + expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][5]).toEqual value: 'mozilla.org', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'variable.parameter.document-rule.css'] + expect(lines[2][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][7]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] + expect(lines[3][1]).toEqual value: 'regexp', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] + expect(lines[3][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[3][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[3][4]).toEqual value: 'https:.*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css'] + expect(lines[3][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[3][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[3][8]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.begin.bracket.curly.css'] + expect(lines[4][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[4][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[4][4]).toEqual value: 'color', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[4][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[4][7]).toEqual value: '#', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] + expect(lines[4][8]).toEqual value: 'f00', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] + expect(lines[4][9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[4][11]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(lines[5][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css'] + + describe '@viewport', -> + it 'tokenises @viewport blocks correctly', -> + {tokens} = grammar.tokenizeLine('@viewport { min-width: 640px; max-width: 800px; }') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'viewport', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[5]).toEqual value: 'min-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[6]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[8]).toEqual value: '640', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[12]).toEqual value: 'max-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[13]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[15]).toEqual value: '800', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[16]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[17]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[19]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenises them across lines', -> + lines = grammar.tokenizeLines """ + @-O-VIEWPORT + { + zoom: 0.75; + min-zoom: 0.5; + max-zoom: 0.9; + } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: '-O-VIEWPORT', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] + expect(lines[1][0]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[2][1]).toEqual value: 'zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[2][4]).toEqual value: '0.75', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[2][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[3][1]).toEqual value: 'min-zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[3][4]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[3][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[4][1]).toEqual value: 'max-zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[4][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[4][4]).toEqual value: '0.9', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[5][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenises injected comments', -> + lines = grammar.tokenizeLines """ + @-ms-viewport/*{*/{/* + ==*/orientation: landscape; + } + """ + expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] + expect(lines[0][1]).toEqual value: '-ms-viewport', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] + expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css'] + expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css'] + expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[1][2]).toEqual value: 'orientation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[1][3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[1][5]).toEqual value: 'landscape', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[1][6]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[2][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'unknown at-rules', -> + it 'correctly parses single-line unknown at-rules closing with semicolons', -> + lines = grammar.tokenizeLines """ + @foo; + @foo ; + @foo a; + @foo (); + @foo (a); + """ + expect(lines[0][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + + expect(lines[1][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + + expect(lines[2][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + expect(lines[2][2]).toEqual value: ' a', scopes: ['source.css', 'meta.at-rule.header.css'] + + expect(lines[3][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + expect(lines[3][2]).toEqual value: ' ()', scopes: ['source.css', 'meta.at-rule.header.css'] + + expect(lines[4][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + expect(lines[4][2]).toEqual value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css'] + + it 'correctly parses single-line unknown at-rules closing with ;', -> + lines = grammar.tokenizeLines """ + @foo bar; + .foo + """ + expect(lines[0][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] + + expect(lines[1][0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(lines[1][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + + describe 'capitalisation', -> + it 'ignores case in at-rules', -> + lines = grammar.tokenizeLines """ + @IMPoRT url("file.css"); + @MEdIA (MAX-WIDTH: 2px){ } + @pAgE :fIRST { } + @NAMEspace "A"; + @foNT-FacE {} + """ + expect(lines[0][1]).toEqual value: 'IMPoRT', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(lines[1][1]).toEqual value: 'MEdIA', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(lines[1][4]).toEqual value: 'MAX-WIDTH', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(lines[2][1]).toEqual value: 'pAgE', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] + expect(lines[2][4]).toEqual value: 'fIRST', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[3][1]).toEqual value: 'NAMEspace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] + expect(lines[4][1]).toEqual value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css'] + + it 'ignores case in property names', -> + lines = grammar.tokenizeLines """ + a{ COLOR: #fff; } + a{ gRId-tEMPLaTe: none; } + a{ bACkgrOUND-iMAGE: none; } + a{ -MOZ-IMAGE: none; } + """ + expect(lines[0][3]).toEqual value: 'COLOR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[1][3]).toEqual value: 'gRId-tEMPLaTe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[2][3]).toEqual value: 'bACkgrOUND-iMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[3][3]).toEqual value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] + + it 'ignores case in property keywords', -> + lines = grammar.tokenizeLines """ + a{ color: INItIaL; } + a{ color: trAnsPAREnT; } + a{ color: rED; } + a{ color: unSET; } + a{ color: NONe; } + a{ style: lOWER-lATIN; } + a{ color: -WebkIT-foo; } + a{ font: HelVETica; } + """ + expect(lines[0][6]).toEqual value: 'INItIaL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[1][6]).toEqual value: 'trAnsPAREnT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[2][6]).toEqual value: 'rED', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(lines[3][6]).toEqual value: 'unSET', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[4][6]).toEqual value: 'NONe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(lines[5][6]).toEqual value: 'lOWER-lATIN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css'] + expect(lines[6][6]).toEqual value: '-WebkIT-foo', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] + expect(lines[7][6]).toEqual value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] + + it 'ignores case in selectors', -> + lines = grammar.tokenizeLines """ + DIV:HOVER { } + #id::BefORE { } + #id::aFTEr { } + TABle:nTH-cHILD(2N+1) {} + htML:NOT(.htiml) {} + I::BACKDROP + I::-mOZ-thing {} + """ + expect(lines[0][0]).toEqual value: 'DIV', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[0][2]).toEqual value: 'HOVER', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[1][3]).toEqual value: 'BefORE', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + expect(lines[2][3]).toEqual value: 'aFTEr', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + expect(lines[3][0]).toEqual value: 'TABle', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[3][2]).toEqual value: 'nTH-cHILD', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[3][4]).toEqual value: '2N+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(lines[4][0]).toEqual value: 'htML', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[4][2]).toEqual value: 'NOT', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[5][0]).toEqual value: 'I', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[5][2]).toEqual value: 'BACKDROP', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + expect(lines[6][2]).toEqual value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + + it 'ignores case in function names', -> + lines = grammar.tokenizeLines """ + a{ color: RGBa(); } + a{ color: hslA(); } + a{ color: URL(); } + a{ content: ATTr(); } + a{ content: CoUNTer(); } + a{ content: cuBIC-beZIER()} + a{ content: sTePs()} + a{ content: cALc(2 + 2)} + """ + expect(lines[0][6]).toEqual value: 'RGBa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[1][6]).toEqual value: 'hslA', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[2][6]).toEqual value: 'URL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] + expect(lines[3][6]).toEqual value: 'ATTr', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[4][6]).toEqual value: 'CoUNTer', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[5][6]).toEqual value: 'cuBIC-beZIER', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] + expect(lines[6][6]).toEqual value: 'sTePs', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] + expect(lines[7][6]).toEqual value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] + + it 'ignores case in unit names', -> + lines = grammar.tokenizeLines """ + a{width: 20EM; } + a{width: 20ReM; } + a{width: 8tURN; } + a{width: 20S; } + a{width: 20CM} + a{width: 2gRAd} + """ + expect(lines[0][5]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[0][6]).toEqual value: 'EM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[1][6]).toEqual value: 'ReM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.rem.css'] + expect(lines[2][2]).toEqual value: 'width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[2][6]).toEqual value: 'tURN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.turn.css'] + expect(lines[3][6]).toEqual value: 'S', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.s.css'] + expect(lines[4][5]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][6]).toEqual value: 'CM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css'] + expect(lines[5][6]).toEqual value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css'] + + describe 'pseudo-classes', -> + it 'tokenizes regular pseudo-classes', -> + {tokens} = grammar.tokenizeLine 'p:first-child' + expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[2]).toEqual value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + + it "doesn't tokenise pseudo-classes if followed by a semicolon or closed bracket", -> + {tokens} = grammar.tokenizeLine('p{ left:left }') + expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[3]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[5]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe ':dir()', -> + it 'tokenises :dir() and its keywords', -> + lines = grammar.tokenizeLines """ + a:dir(ltr ){ } + *:dir( rtl){ } + """ + expect(lines[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[0][2]).toEqual value: 'dir', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[0][4]).toEqual value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] + expect(lines[0][5]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] + expect(lines[0][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[1][0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] + expect(lines[1][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[1][2]).toEqual value: 'dir', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[1][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][4]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] + expect(lines[1][5]).toEqual value: 'rtl', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] + expect(lines[1][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'allows :dir() to include comments and newlines', -> + lines = grammar.tokenizeLines """ + :DIR(/** + ==*/ltr/* + */) + """ + expect(lines[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(lines[0][1]).toEqual value: 'DIR', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(lines[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[0][3]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[0][4]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] + expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] + expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[1][2]).toEqual value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] + expect(lines[1][3]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][0]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][1]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + + describe ':lang()', -> + it 'tokenizes :lang()', -> + {tokens} = grammar.tokenizeLine ':lang(zh-Hans-CN,es-419)' + expect(tokens[0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[3]).toEqual value: 'zh-Hans-CN', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css'] + expect(tokens[4]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] + expect(tokens[5]).toEqual value: 'es-419', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css'] + expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'does not tokenize unquoted language ranges containing asterisks', -> + {tokens} = grammar.tokenizeLine ':lang(zh-*-CN)' + expect(tokens[3]).toEqual value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css'] + + it 'tokenizes language ranges containing asterisks quoted as strings', -> + {tokens} = grammar.tokenizeLine ':lang("zh-*-CN",\'*-ab-\')' + expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[4]).toEqual value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'support.constant.language-range.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[6]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] + expect(tokens[7]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[8]).toEqual value: '*-ab-', scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'support.constant.language-range.css'] + expect(tokens[9]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + + describe ':not()', -> + it 'tokenises other selectors inside :not()', -> + {tokens} = grammar.tokenizeLine('*:not(.class-name):not(div) {}') + expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[2]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[5]).toEqual value: 'class-name', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[8]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[10]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'tokenises injected comments', -> + {tokens} = grammar.tokenizeLine('*:not(/*(*/.class-name/*)*/):not(/*b*/) {}') + expect(tokens[2]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] + expect(tokens[6]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[7]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[8]).toEqual value: 'class-name', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] + expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[13]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[14]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[15]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[16]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[17]).toEqual value: 'b', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] + expect(tokens[18]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[19]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + + describe ':nth-*()', -> + it 'tokenizes :nth-child()', -> + tokens = grammar.tokenizeLines ''' + :nth-child(2n+1) + :nth-child(2n -1) + :nth-child(-2n+ 1) + :nth-child(-2n - 1) + :nth-child(odd) + :nth-child(even) + :nth-child( odd ) + :nth-child( even ) + ''' + expect(tokens[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[0][1]).toEqual value: 'nth-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[0][3]).toEqual value: '2n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[0][4]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[1][3]).toEqual value: '2n -1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[2][3]).toEqual value: '-2n+ 1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[3][3]).toEqual value: '-2n - 1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[4][3]).toEqual value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] + expect(tokens[5][3]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] + expect(tokens[6][3]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] + expect(tokens[6][4]).toEqual value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] + expect(tokens[7][4]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] + expect(tokens[7][5]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] + + it 'tokenizes :nth-last-child()', -> + tokens = grammar.tokenizeLines ''' + :nth-last-child(2n) + :nth-last-child( -2n) + :nth-last-child( 2n ) + :nth-last-child(even) + ''' + expect(tokens[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[0][1]).toEqual value: 'nth-last-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[0][3]).toEqual value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[0][4]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[1][4]).toEqual value: '-2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[2][4]).toEqual value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[2][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[3][3]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] + + it 'tokenizes :nth-of-type()', -> + tokens = grammar.tokenizeLines ''' + img:nth-of-type(+n+1) + img:nth-of-type(-n+1) + img:nth-of-type(n+1) + ''' + expect(tokens[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[0][2]).toEqual value: 'nth-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[0][4]).toEqual value: '+n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[0][5]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[1][4]).toEqual value: '-n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[2][4]).toEqual value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + + it 'tokenizes ::nth-last-of-type()', -> + tokens = grammar.tokenizeLines ''' + h1:nth-last-of-type(-1) + h1:nth-last-of-type(+2) + h1:nth-last-of-type(3) + ''' + expect(tokens[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[0][2]).toEqual value: 'nth-last-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + expect(tokens[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[0][4]).toEqual value: '-1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[0][5]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[1][4]).toEqual value: '+2', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + expect(tokens[2][4]).toEqual value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] + + describe 'pseudo-elements', -> + # :first-line, :first-letter, :before and :after + it 'tokenizes both : and :: notations for pseudo-elements introduced in CSS 1 and 2', -> + {tokens} = grammar.tokenizeLine '.opening:first-letter' + expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'opening', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + expect(tokens[2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(tokens[3]).toEqual value: 'first-letter', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + + {tokens} = grammar.tokenizeLine 'q::after' + expect(tokens[0]).toEqual value: 'q', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(tokens[2]).toEqual value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + + it 'tokenizes both : and :: notations for vendor-prefixed pseudo-elements', -> + {tokens} = grammar.tokenizeLine ':-ms-input-placeholder' + expect(tokens[0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '-ms-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + + {tokens} = grammar.tokenizeLine '::-webkit-input-placeholder' + expect(tokens[0]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + + it 'only tokenizes the :: notation for other pseudo-elements', -> + {tokens} = grammar.tokenizeLine '::selection' + expect(tokens[0]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(tokens[1]).toEqual value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + + {tokens} = grammar.tokenizeLine ':selection' + expect(tokens[0]).toEqual value: ':selection', scopes: ['source.css', 'meta.selector.css'] + + describe 'compound selectors', -> + it 'tokenizes the combination of type selectors followed by class selectors', -> + {tokens} = grammar.tokenizeLine 'very-custom.class' + expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + expect(tokens[1]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] + expect(tokens[2]).toEqual value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] + + it 'tokenizes the combination of type selectors followed by pseudo-classes', -> + {tokens} = grammar.tokenizeLine 'very-custom:hover' + expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] + expect(tokens[2]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] + + it 'tokenizes the combination of type selectors followed by pseudo-elements', -> + {tokens} = grammar.tokenizeLine 'very-custom::shadow' + expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + expect(tokens[1]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] + expect(tokens[2]).toEqual value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] + + describe 'property lists (declaration blocks)', -> + it 'tokenizes inline property lists', -> + {tokens} = grammar.tokenizeLine 'div { font-size: inherit; }' + expect(tokens[4]).toEqual value: 'font-size', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[7]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenizes compact inline property lists', -> + {tokens} = grammar.tokenizeLine 'div{color:inherit;float:left}' + expect(tokens[2]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[4]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[6]).toEqual value: 'float', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[8]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenizes multiple inline property lists', -> + tokens = grammar.tokenizeLines ''' + very-custom { color: inherit } + another-one { display : none ; } + ''' + expect(tokens[0][0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + expect(tokens[0][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[0][7]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(tokens[1][0]).toEqual value: 'another-one', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + expect(tokens[1][4]).toEqual value: 'display', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[1][5]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[1][8]).toEqual value: 'none', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[1][9]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[1][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[1][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenizes custom properties', -> + {tokens} = grammar.tokenizeLine ':root { --white: #FFF; }' + expect(tokens[5]).toEqual value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css'] + + it 'tokenises commas between property values', -> + {tokens} = grammar.tokenizeLine('a{ text-shadow: a, b; }') + expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] + + it 'tokenises superfluous semicolons', -> + lines = grammar.tokenizeLines ''' + .test{ width: 20em;;;;;;;;; + ;;;;;;;;;height: 10em; } + ''' + for i in [0..8] + expect(lines[0][i+9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[1][i]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[1][9]).toEqual value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + + describe 'values', -> + it 'tokenizes color keywords', -> + {tokens} = grammar.tokenizeLine '#jon { color: snow; }' + expect(tokens[8]).toEqual value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css'] + + it 'tokenises RGBA values in hex notation', -> + {tokens} = grammar.tokenizeLine('p{ color: #f030; }') + expect(tokens[6]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] + expect(tokens[7]).toEqual value: 'f030', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] + expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('a{ color: #CAFEBABE; }') + expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] + expect(tokens[7]).toEqual value: 'CAFEBABE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] + expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('a{ color: #CAFEBABEF; }') + expect(tokens[6]).toEqual value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + + it 'tokenizes common font names', -> + {tokens} = grammar.tokenizeLine 'p { font-family: Verdana, Helvetica, sans-serif; }' + expect(tokens[7]).toEqual value: 'Verdana', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] + expect(tokens[10]).toEqual value: 'Helvetica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] + expect(tokens[13]).toEqual value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] + + it 'tokenizes predefined list style types', -> + {tokens} = grammar.tokenizeLine 'ol.myth { list-style-type: cjk-earthly-branch }' + expect(tokens[9]).toEqual value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css'] + + it 'tokenizes numeric values', -> + {tokens} = grammar.tokenizeLine 'div { font-size: 14px; }' + expect(tokens[7]).toEqual value: '14', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + + it 'does not tokenize invalid numeric values', -> + {tokens} = grammar.tokenizeLine 'div { font-size: test14px; }' + expect(tokens[7]).toEqual value: 'test14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + + {tokens} = grammar.tokenizeLine 'div { font-size: test-14px; }' + expect(tokens[7]).toEqual value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + + it 'tokenizes vendor-prefixed values', -> + {tokens} = grammar.tokenizeLine '.edge { cursor: -webkit-zoom-in; }' + expect(tokens[8]).toEqual value: '-webkit-zoom-in', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] + + {tokens} = grammar.tokenizeLine '.edge { width: -moz-min-content; }' + expect(tokens[8]).toEqual value: '-moz-min-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] + + {tokens} = grammar.tokenizeLine '.edge { display: -ms-grid; }' + expect(tokens[8]).toEqual value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] + + it 'tokenizes custom variables', -> + {tokens} = grammar.tokenizeLine 'div { color: var(--primary-color) }' + expect(tokens[9]).toEqual value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] + + it 'tokenises numeric values correctly', -> + lines = grammar.tokenizeLines """ + .a { a: 12em } + .a { a: 4.01ex } + .a { a: -456.8ch } + .a { a: 0.0REM } + .a { a: +0.0vh } + .a { a: -0.0vw } + .a { a: .6px } + .a { a: 10e3mm } + .a { a: 10E3cm } + .a { a: -3.4e+2In } + .a { a: -3.4e-2ch } + .a { a: +.5E-2% } + .a { a: -3.4e-2% } + """ + expect(lines[0][8]).toEqual value: '12', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[0][9]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[1][8]).toEqual value: '4.01', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[1][9]).toEqual value: 'ex', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ex.css'] + expect(lines[2][8]).toEqual value: '-456.8', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[2][9]).toEqual value: 'ch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ch.css'] + expect(lines[3][8]).toEqual value: '0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[3][9]).toEqual value: 'REM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.rem.css'] + expect(lines[4][8]).toEqual value: '+0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[4][9]).toEqual value: 'vh', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.vh.css'] + expect(lines[5][8]).toEqual value: '-0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[5][9]).toEqual value: 'vw', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.vw.css'] + expect(lines[6][8]).toEqual value: '.6', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[6][9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[7][8]).toEqual value: '10e3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[7][9]).toEqual value: 'mm', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.mm.css'] + expect(lines[8][8]).toEqual value: '10E3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[8][9]).toEqual value: 'cm', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css'] + expect(lines[9][8]).toEqual value: '-3.4e+2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[9][9]).toEqual value: 'In', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.in.css'] + expect(lines[10][8]).toEqual value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[10][9]).toEqual value: 'ch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ch.css'] + expect(lines[11][8]).toEqual value: '+.5E-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[11][9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(lines[12][8]).toEqual value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(lines[12][9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + + describe 'functional notation', -> + describe 'attr()', -> + it 'tokenises parameters correctly and case-insensitively', -> + {tokens} = grammar.tokenizeLine('a{content:aTTr(data-width px, inherit)}') + expect(tokens[4]).toEqual value: 'aTTr', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[6]).toEqual value: 'data-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] + expect(tokens[11]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.constant.property-value.css'] + expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[13]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'matches variables', -> + {tokens} = grammar.tokenizeLine('a{content:ATTR(VAR(--name) px, "N/A")}') + expect(tokens[4]).toEqual value: 'ATTR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[6]).toEqual value: 'VAR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[11]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(tokens[12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] + expect(tokens[14]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[15]).toEqual value: 'N/A', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] + expect(tokens[16]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[17]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + + describe 'calc()', -> + it 'tokenises calculations', -> + lines = grammar.tokenizeLines """ + a{ + width: calc(3px + -1em); + width: calc(3px - -1em); + width: calc(3px * 2); + width: calc(3px / 2); + } + """ + expect(lines[1][4]).toEqual value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] + expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][6]).toEqual value: '3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + expect(lines[1][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[1][9]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] + expect(lines[1][11]).toEqual value: '-1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + expect(lines[1][12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[1][13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][9]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] + expect(lines[2][11]).toEqual value: '-1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + expect(lines[2][12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[3][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[3][9]).toEqual value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] + expect(lines[4][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[4][9]).toEqual value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] + expect(lines[4][11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + + it 'requires whitespace around + and - operators', -> + {tokens} = grammar.tokenizeLine('a{ width: calc(3px+1em); }') + expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[10]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] + expect(tokens[11]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + expect(tokens[12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + + {tokens} = grammar.tokenizeLine('a{ width: calc(3px--1em); height: calc(10-1em);}') + expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[10]).toEqual value: '--1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] + expect(tokens[19]).toEqual value: '10', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + expect(tokens[20]).toEqual value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] + + it 'does not require whitespace around * and / operators', -> + {tokens} = grammar.tokenizeLine('a{ width: calc(3px*2); }') + expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[10]).toEqual value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] + expect(tokens[11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + + {tokens} = grammar.tokenizeLine('a{ width: calc(3px/2); }') + expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[10]).toEqual value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] + expect(tokens[11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + + it 'matches variable expansions inside calculations', -> + {tokens} = grammar.tokenizeLine('.foo { margin-top: calc(var(--gap) + 1px); }') + expect(tokens[8]).toEqual value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] + expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[10]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(tokens[11]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[12]).toEqual value: '--gap', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(tokens[13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[15]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] + expect(tokens[17]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] + expect(tokens[18]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[19]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[20]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[22]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'colours', -> + it 'tokenises colour functions correctly', -> + {tokens} = grammar.tokenizeLine('a{ color: rgb(187,255,221); }') + expect(tokens[6]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: '187', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[10]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[12]).toEqual value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + + {tokens} = grammar.tokenizeLine('a{ color: RGBa( 100%, 0% ,20.17% ,.5 ); }') + expect(tokens[6]).toEqual value: 'RGBa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[9]).toEqual value: '100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[10]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[13]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[14]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[17]).toEqual value: '20.17', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[18]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(tokens[20]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[21]).toEqual value: '.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[23]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + + {tokens} = grammar.tokenizeLine('a{color:HSL(0, 00100%,50%)}') + expect(tokens[4]).toEqual value: 'HSL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[9]).toEqual value: '00100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[10]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[12]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[13]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(tokens[14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + + {tokens} = grammar.tokenizeLine('a{color:HSLa(2,.0%,1%,.7)}') + expect(tokens[4]).toEqual value: 'HSLa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[6]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[8]).toEqual value: '.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[11]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[12]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(tokens[13]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[14]).toEqual value: '.7', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'matches variables as colour components', -> + {tokens} = grammar.tokenizeLine('a{ color: RGBA(var(--red), 0% , 20%, .2)}') + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[10]).toEqual value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + + it 'matches comments between colour components', -> + {tokens} = grammar.tokenizeLine('a{ color: rgba(/**/255/*=*/,0,/*2.2%*/51/*,*/0.2)}') + expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[10]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[11]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[12]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] + expect(tokens[13]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[14]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[17]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[19]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[20]).toEqual value: '51', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[21]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[22]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] + expect(tokens[23]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[24]).toEqual value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] + + it 'allows colour components to be split across lines', -> + lines = grammar.tokenizeLines """ + .frost{ + background-color: rgba( + var(--red), /* Red */ + var(--green), /* Green */ + var(--blue), /* Blue */ + /* var(--test), + /**/var(--opacity) /* Transparency */ + ); + } + """ + expect(lines[1][4]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][3]).toEqual value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(lines[2][4]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][8]).toEqual value: ' Red ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] + expect(lines[3][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(lines[3][3]).toEqual value: '--green', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(lines[3][5]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(lines[3][8]).toEqual value: ' Green ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] + expect(lines[4][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(lines[4][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[4][3]).toEqual value: '--blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(lines[4][4]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[4][5]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(lines[4][8]).toEqual value: ' Blue ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] + expect(lines[4][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[5][1]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[5][2]).toEqual value: ' var(--test),', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] + expect(lines[6][0]).toEqual value: ' /*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] + expect(lines[6][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[6][2]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(lines[6][3]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[6][4]).toEqual value: '--opacity', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(lines[6][5]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[6][7]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[6][8]).toEqual value: ' Transparency ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] + expect(lines[6][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[7][1]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + + describe 'gradients', -> + it 'tokenises linear gradients', -> + {tokens} = grammar.tokenizeLine('a{ background-image: linear-gradient( 45deg, blue, red ); }') + expect(tokens[6]).toEqual value: 'linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[9]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] + expect(tokens[10]).toEqual value: 'deg', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.deg.css'] + expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] + expect(tokens[13]).toEqual value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(tokens[14]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] + expect(tokens[16]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(tokens[18]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[19]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine('a{ background-image: LINear-graDIEnt( ellipse to left top, blue, red);') + expect(tokens[6]).toEqual value: 'LINear-graDIEnt', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] + expect(tokens[9]).toEqual value: 'ellipse', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + expect(tokens[11]).toEqual value: 'to', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] + expect(tokens[13]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + expect(tokens[15]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] + expect(tokens[18]).toEqual value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(tokens[19]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] + expect(tokens[21]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] + + it 'tokenises radial gradients', -> + {tokens} = grammar.tokenizeLine('a{ background-image: radial-gradient(farthest-corner at 45px 45px , #f00 0%, #00f 100%);}') + expect(tokens[6]).toEqual value: 'radial-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: 'farthest-corner', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + expect(tokens[10]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] + expect(tokens[12]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] + expect(tokens[13]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[15]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] + expect(tokens[16]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] + expect(tokens[20]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] + expect(tokens[21]).toEqual value: 'f00', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] + expect(tokens[23]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] + expect(tokens[24]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + + {tokens} = grammar.tokenizeLine('a{ background-image: RADial-gradiENT(16px at 60px 50%,#000 0%, #000 14px, rgba(0,0,0,.3) 18px, transparent 19px)}') + expect(tokens[6]).toEqual value: 'RADial-gradiENT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: '16', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] + expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[11]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] + expect(tokens[13]).toEqual value: '60', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] + expect(tokens[14]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[16]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] + expect(tokens[17]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] + expect(tokens[19]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] + expect(tokens[20]).toEqual value: '000', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] + expect(tokens[33]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(tokens[34]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[35]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[36]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(tokens[41]).toEqual value: '.3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(tokens[42]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[48]).toEqual value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + + it 'matches gradients that span multiple lines with injected comments', -> + lines = grammar.tokenizeLines """ + a{ + background-image: raDIAL-gradiENT( + ellipse farthest-corner/*@*/at/*@*/470px 47px,/*=== + ========*/#FFFF80 20%, rgba(204, 153, 153, 0.4) 30%,/*))))))))}*/#E6E6FF 60%); } + """ + expect(lines[1][4]).toEqual value: 'raDIAL-gradiENT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] + expect(lines[2][1]).toEqual value: 'ellipse', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + expect(lines[2][3]).toEqual value: 'farthest-corner', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][5]).toEqual value: '@', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] + expect(lines[2][6]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[2][7]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] + expect(lines[2][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][11]).toEqual value: '470', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] + expect(lines[2][12]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(lines[2][16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[2][17]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[2][18]).toEqual value: '===', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] + expect(lines[3][0]).toEqual value: '========', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] + expect(lines[3][2]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] + expect(lines[3][3]).toEqual value: 'FFFF80', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] + expect(lines[3][9]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[3][10]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[3][20]).toEqual value: '0.4', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[3][21]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[3][26]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[3][27]).toEqual value: '))))))))}', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] + expect(lines[3][28]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[3][29]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] + expect(lines[3][30]).toEqual value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] + + it 'highlights vendored gradient functions', -> + lines = grammar.tokenizeLines """ + .grad { + background-image: -webkit-linear-gradient(top, /* For Chrome 25 and Safari 6, iOS 6.1, Android 4.3 */ hsl(0, 80%, 70%), #bada55); + background-image: -moz-linear-gradient(top, /* For Firefox (3.6 to 15) */ hsl(0, 80%, 70%), #bada55); + background-image: -o-linear-gradient(top, /* For old Opera (11.1 to 12.0) */ hsl(0, 80%, 70%), #bada55); + } + """ + expect(lines[1][4]).toEqual value: '-webkit-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] + expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][6]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + expect(lines[1][10]).toEqual value: ' For Chrome 25 and Safari 6, iOS 6.1, Android 4.3 ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] + expect(lines[1][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[1][22]).toEqual value: '70', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[1][23]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(lines[1][24]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[1][27]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] + expect(lines[1][28]).toEqual value: 'bada55', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] + expect(lines[1][29]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][4]).toEqual value: '-moz-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] + expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][6]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] + expect(lines[2][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[2][10]).toEqual value: ' For Firefox (3.6 to 15) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] + expect(lines[2][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[2][14]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][24]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][29]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[3][4]).toEqual value: '-o-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] + expect(lines[3][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[3][10]).toEqual value: ' For old Opera (11.1 to 12.0) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] + expect(lines[3][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[3][14]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + + it 'highlights antique Webkit syntax as deprecated', -> + lines = grammar.tokenizeLines """ + .grad { + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, + from( rgb(0, 171, 235)), + color-stop(0.5, rgb(255, 255, 255)), + color-stop(0.5, rgb(102, 204, 0)), + to(rgb(255, 255, 255))), + -webkit-gradient(radial, 45 45, 10, 52 50, 30, from(#A7D30C), to(rgba(1,159,98,0)), color-stop(90%, #019F62)), + -webkit-gradient(radial, 105 105, 20, 112 120, 50, from(#ff5f98), to(rgba(255,1,136,0)), color-stop(75%, #ff0188)), + -webkit-gradient(radial, 95 15, 15, 102 20, 40, from(#00c9ff), to(rgba(0,201,255,0)), color-stop(80%, #00b5e2)), + -webkit-gradient(radial, 0 150, 50, 0 140, 90, from(#f4f201), to(rgba(228, 199,0,0)), color-stop(80%, #e4c700)); + } + """ + expect(lines[1][4]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] + expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][6]).toEqual value: 'linear', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] + expect(lines[1][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[1][19]).toEqual value: '100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] + expect(lines[1][20]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(lines[2][1]).toEqual value: 'from', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] + expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][4]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][9]).toEqual value: '171', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[2][10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(lines[2][14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[3][1]).toEqual value: 'color-stop', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] + expect(lines[3][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[3][3]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] + expect(lines[3][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[3][16]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[3][17]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[4][1]).toEqual value: 'color-stop', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] + expect(lines[4][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[4][3]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] + expect(lines[4][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[4][6]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[4][7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[4][8]).toEqual value: '102', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[4][9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(lines[4][11]).toEqual value: '204', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[4][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] + expect(lines[4][14]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] + expect(lines[4][15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[4][16]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[4][17]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[5][1]).toEqual value: 'to', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] + expect(lines[5][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[5][12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[5][13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[5][14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[5][15]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] + expect(lines[6][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] + expect(lines[6][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[6][3]).toEqual value: 'radial', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] + expect(lines[6][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[6][8]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] + expect(lines[6][31]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] + expect(lines[7][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] + expect(lines[7][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[9][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] + expect(lines[9][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[9][3]).toEqual value: 'radial', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] + expect(lines[9][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] + expect(lines[9][6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] + expect(lines[9][8]).toEqual value: '150', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] + expect(lines[9][54]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[9][55]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[10][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'other functions', -> + it 'tokenises basic-shape functions', -> + lines = grammar.tokenizeLines """ + a{ + shape-outside: circle(20em/*=*/at 50% 50%); + shape-outside: inset(1em, 1em, 1em, 1em); + } + """ + expect(lines[1][4]).toEqual value: 'circle', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'support.function.shape.css'] + expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][6]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] + expect(lines[1][7]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[1][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[1][9]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css'] + expect(lines[1][10]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(lines[1][11]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'keyword.operator.shape.css'] + expect(lines[1][13]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] + expect(lines[1][14]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(lines[1][16]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] + expect(lines[1][17]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] + expect(lines[1][18]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][4]).toEqual value: 'inset', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'support.function.shape.css'] + expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][6]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] + expect(lines[2][7]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[2][8]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] + expect(lines[2][10]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] + expect(lines[2][11]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[2][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] + expect(lines[2][14]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] + expect(lines[2][15]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[2][16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] + expect(lines[2][18]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] + expect(lines[2][19]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(lines[2][20]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'tokenises OpenType feature functions', -> + lines = grammar.tokenizeLines """ + .font{ + font-variant-alternates: stylistic(user-defined-ident); + font-variant-alternates: styleset(user-defined-ident); + font-variant-alternates: character-variant(user-defined-ident); + font-variant-alternates: swash(user-defined-ident); + font-variant-alternates: ornaments(user-defined-ident); + font-variant-alternates: annotation(user-defined-ident); + font-variant-alternates: swash(ident1) annotation(ident2); + } + """ + expect(lines[1][4]).toEqual value: 'stylistic', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(lines[1][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[2][4]).toEqual value: 'styleset', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[2][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(lines[2][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[3][4]).toEqual value: 'character-variant', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[3][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[3][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(lines[3][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[4][4]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[4][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[4][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(lines[4][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[5][4]).toEqual value: 'ornaments', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[5][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[5][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(lines[5][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[6][4]).toEqual value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[6][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[6][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(lines[6][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[7][4]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[7][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[7][6]).toEqual value: 'ident1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(lines[7][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[7][9]).toEqual value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[7][10]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[7][11]).toEqual value: 'ident2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] + expect(lines[7][12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'tokenises image-set()', -> + lines = grammar.tokenizeLines """ + a{ + background-image: image-set( "foo.png" 1x, + "foo-2x.png" 2x, + "foo-print.png" 600dpi ); + } + """ + expect(lines[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(lines[0][1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(lines[1][1]).toEqual value: 'background-image', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[1][4]).toEqual value: 'image-set', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] + expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(lines[1][7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[1][8]).toEqual value: 'foo.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] + expect(lines[1][9]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[1][11]).toEqual value: '1x', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.other.density.css'] + expect(lines[1][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] + expect(lines[2][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[2][2]).toEqual value: 'foo-2x.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] + expect(lines[2][3]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[2][5]).toEqual value: '2x', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.other.density.css'] + expect(lines[2][6]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] + expect(lines[3][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[3][2]).toEqual value: 'foo-print.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] + expect(lines[3][3]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[3][5]).toEqual value: '600', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css'] + expect(lines[3][6]).toEqual value: 'dpi', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css', 'keyword.other.unit.dpi.css'] + expect(lines[3][8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] + expect(lines[3][9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'timing-functions', -> + it 'tokenises them correctly', -> + {tokens} = grammar.tokenizeLine('a{ zoom: cubic-bezier(/**/1.2,/*=*/0,0,0/**/)}') + expect(tokens[6]).toEqual value: 'cubic-bezier', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[10]).toEqual value: '1.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] + expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] + expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[13]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css'] + expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[15]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] + expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] + expect(tokens[17]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] + expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] + expect(tokens[19]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] + expect(tokens[20]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[21]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[22]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'highlights the "start" and "end" keywords', -> + {tokens} = grammar.tokenizeLine('a{ before: steps(0, start); after: steps(1, end); }') + expect(tokens[6]).toEqual value: 'steps', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] + expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] + expect(tokens[11]).toEqual value: 'start', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css'] + expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[23]).toEqual value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css'] + + describe 'variables', -> + it 'scopes var() statements as variables', -> + {tokens} = grammar.tokenizeLine('a{color: var(--name)}') + expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[2]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[5]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[7]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('a{color: var( --name )}') + expect(tokens[5]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'allows injected comments', -> + {tokens} = grammar.tokenizeLine('a{ color: var( /*=*/ --something ) }') + expect(tokens[6]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[10]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css'] + expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[13]).toEqual value: '--something', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + + it 'tokenises fallback values', -> + {tokens} = grammar.tokenizeLine('.bar{ width: var(--page-width, /*;;;);*/ 2); }') + expect(tokens[7]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] + expect(tokens[8]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[9]).toEqual value: '--page-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] + expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.separator.list.comma.css'] + expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[13]).toEqual value: ';;;);', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css'] + expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[16]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'constant.numeric.css'] + expect(tokens[17]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[18]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + + it 'does not tokenise functions with whitespace between name and parameters', -> + {tokens} = grammar.tokenizeLine('a{ p: attr (title); }') + expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[3]).toEqual value: 'p', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css'] + expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: 'attr (title', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('a{url:url (s)}') + expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[2]).toEqual value: 'url', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css'] + expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[4]).toEqual value: 'url (s', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[5]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('a{content:url ("http://github.com/");}') + expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[2]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[4]).toEqual value: 'url (', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[6]).toEqual value: 'http://github.com/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('a{content: url (http://a.pl/)}') + expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[2]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[5]).toEqual value: 'url (http://a.pl/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + {tokens} = grammar.tokenizeLine('a{ color: rgb (187,255,221); }') + expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: 'rgb (', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[7]).toEqual value: '187', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[8]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] + expect(tokens[9]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] + expect(tokens[11]).toEqual value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[13]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[15]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'Unicode ranges', -> + it 'tokenises single codepoints', -> + {tokens} = grammar.tokenizeLine('a{ a: U+A5 }') + expect(tokens[6]).toEqual value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + + it 'tokenises codepoint ranges', -> + {tokens} = grammar.tokenizeLine('a{ a: U+0025-00FF }') + expect(tokens[6]).toEqual value: 'U+0025', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] + expect(tokens[8]).toEqual value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + + {tokens} = grammar.tokenizeLine('a{ unicode-range: u+0-7F }') + expect(tokens[6]).toEqual value: 'u+0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] + expect(tokens[8]).toEqual value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + + it 'tokenises wildcard ranges', -> + {tokens} = grammar.tokenizeLine('a{ unicode-range: U+4?? }') + expect(tokens[6]).toEqual value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + + {tokens} = grammar.tokenizeLine('a{ unicode-range: U+0025-00FF, U+4?? }') + expect(tokens[6]).toEqual value: 'U+0025', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] + expect(tokens[8]).toEqual value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] + expect(tokens[11]).toEqual value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] + + describe 'escape sequences', -> + it 'tokenizes escape sequences in single-quoted strings', -> + {tokens} = grammar.tokenizeLine "very-custom { content: '\\c0ffee' }" + + expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[4]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[7]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[8]).toEqual value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css'] + + it 'tokenizes escape sequences in double-quoted strings', -> + {tokens} = grammar.tokenizeLine 'very-custom { content: "\\c0ffee" }' + + expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] + expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[4]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[8]).toEqual value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css'] + + it 'tokenises escape sequences in selectors', -> + {tokens} = grammar.tokenizeLine('\\61 \\{ { } \\}') + expect(tokens[0]).toEqual value: '\\61', scopes: ['source.css', 'constant.character.escape.codepoint.css'] + expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'constant.character.escape.css'] + expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + expect(tokens[8]).toEqual value: '\\}', scopes: ['source.css', 'constant.character.escape.css'] + + {tokens} = grammar.tokenizeLine('\\61\\ \\. \\@media {}') # Matches <.><@media> + expect(tokens[0]).toEqual value: '\\61', scopes: ['source.css', 'constant.character.escape.codepoint.css'] + expect(tokens[1]).toEqual value: '\\ ', scopes: ['source.css', 'constant.character.escape.css'] + expect(tokens[2]).toEqual value: '\\.', scopes: ['source.css', 'constant.character.escape.css'] + expect(tokens[4]).toEqual value: '\\@', scopes: ['source.css', 'constant.character.escape.css'] + expect(tokens[5]).toEqual value: 'media', scopes: ['source.css', 'meta.selector.css'] + expect(tokens[6]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[7]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + + it 'tokenises escape sequences in property lists', -> + {tokens} = grammar.tokenizeLine('a { \\77\\69\\64\\74\\68: 20px; }') # Same as writing "width: 20px" + expect(tokens[4]).toEqual value: '\\77', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] + expect(tokens[5]).toEqual value: '\\69', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] + expect(tokens[6]).toEqual value: '\\64', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] + expect(tokens[7]).toEqual value: '\\74', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] + expect(tokens[8]).toEqual value: '\\68', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] + expect(tokens[9]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + + it 'tokenises escape sequences in property values', -> + {tokens} = grammar.tokenizeLine('a { content: \\1F764; }') + expect(tokens[7]).toEqual value: '\\1F764', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.character.escape.codepoint.css'] + expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'unclosed strings', -> + it 'highlights an unterminated string as an error', -> + {tokens} = grammar.tokenizeLine("a{ content: 'aaaa") + expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[7]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] + + {tokens} = grammar.tokenizeLine('a{ content: "aaaa') + expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[7]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] + + it "knows when a string is line-wrapped", -> + lines = grammar.tokenizeLines """ + a{ + content: "aaaaa\\\\\\ + aaa"; color: red; + } + """ + expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[1][5]).toEqual value: 'aaaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] + expect(lines[1][6]).toEqual value: '\\\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.css'] + expect(lines[1][7]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.newline.css'] + expect(lines[2][0]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] + expect(lines[2][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(lines[2][2]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[2][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + + lines = grammar.tokenizeLines """ + a{ + content: 'aaaaa\\\\\\ + aaa'; color: red; + } + """ + expect(lines[1][4]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(lines[1][5]).toEqual value: 'aaaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css'] + expect(lines[1][6]).toEqual value: '\\\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.css'] + expect(lines[1][7]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.newline.css'] + expect(lines[2][0]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css'] + expect(lines[2][1]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] + expect(lines[2][2]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[2][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + + it 'highlights escape sequences inside invalid strings', -> + {tokens} = grammar.tokenizeLine('a{ content: "aaa\\"aa') + expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[7]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] + expect(tokens[8]).toEqual value: '\\"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css'] + expect(tokens[9]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] + + {tokens} = grammar.tokenizeLine("a{ content: 'aaa\\'aa") + expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] + expect(tokens[7]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] + expect(tokens[8]).toEqual value: "\\'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css'] + expect(tokens[9]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] + + it 'highlights unclosed lines in line-wrapped strings', -> + lines = grammar.tokenizeLines """ + a{ + content: "aaa\\"aa\\ + aaaa + aaaa; color: red; + } + """ + expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(lines[1][5]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] + expect(lines[1][6]).toEqual value: '\\"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.css'] + expect(lines[1][7]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] + expect(lines[1][8]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.newline.css'] + expect(lines[2][0]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] + expect(lines[3][0]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(lines[3][1]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[3][3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(lines[3][4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(lines[3][6]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] + expect(lines[3][7]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'comments', -> + it 'tokenises comments inside @import statements', -> + {tokens} = grammar.tokenizeLine('@import /* url("name"); */ "1.css";') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[4]).toEqual value: ' url("name"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] + expect(tokens[5]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[8]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] + expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine('@import/*";"*/ url("2.css");') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: '";"', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[6]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] + expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[8]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[9]).toEqual value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] + expect(tokens[10]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + {tokens} = grammar.tokenizeLine('@import url("3.css") print /* url(";"); */;') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] + expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] + expect(tokens[6]).toEqual value: '3.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[10]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] + expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[13]).toEqual value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] + expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] + + it 'tokenises comments inside @font-face statements', -> + {tokens} = grammar.tokenizeLine('@font-face/*"{;}"*/{}') + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'font-face', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: '"{;}"', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenizes comments before media queries', -> + {tokens} = grammar.tokenizeLine '/* comment */ @media' + + expect(tokens[0]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[1]).toEqual value: ' comment ', scopes: ['source.css', 'comment.block.css'] + expect(tokens[2]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[4]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[5]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + + it 'tokenizes comments after media queries', -> + {tokens} = grammar.tokenizeLine '@media/* comment */ ()' + + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[3]).toEqual value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + + it 'tokenizes comments inside query lists', -> + {tokens} = grammar.tokenizeLine '@media (max-height: 40em/* comment */)' + + expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] + expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] + expect(tokens[4]).toEqual value: 'max-height', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] + expect(tokens[7]).toEqual value: '40', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] + expect(tokens[8]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] + expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[10]).toEqual value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] + expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] + + it 'tokenizes inline comments', -> + {tokens} = grammar.tokenizeLine 'section {border:4px/*padding:1px*/}' + + expect(tokens[0]).toEqual value: 'section', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[3]).toEqual value: 'border', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[5]).toEqual value: '4', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[6]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[7]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(tokens[8]).toEqual value: 'padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] + expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it 'tokenizes multi-line comments', -> + lines = grammar.tokenizeLines """ + section { + border:4px /*1px; + padding:1px*/ + } + """ + + expect(lines[1][5]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(lines[1][6]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] + expect(lines[1][7]).toEqual value: '1px;', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] + + expect(lines[2][0]).toEqual value: ' padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] + expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] + + expect(lines[3][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + describe 'Animations', -> + it 'does not confuse animation names with predefined keywords', -> + tokens = grammar.tokenizeLines ''' + .animated { + animation-name: orphan-black; + animation-name: line-scale; + } + ''' + expect(tokens[1][4]).toEqual value: 'orphan-black', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[2][4]).toEqual value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + + describe 'Transforms', -> + it 'tokenizes transform functions', -> + tokens = grammar.tokenizeLines ''' + .transformed { + transform: matrix(0, 1.5, -1.5, 0, 0, 100px); + transform: rotate(90deg) translateX(100px) scale(1.5); + } + ''' + expect(tokens[1][1]).toEqual value: 'transform', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[1][4]).toEqual value: 'matrix', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] + expect(tokens[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.begin.bracket.round.css'] + expect(tokens[1][6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[1][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] + expect(tokens[1][12]).toEqual value: '-1.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[1][22]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[1][23]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.end.bracket.round.css'] + expect(tokens[2][4]).toEqual value: 'rotate', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] + expect(tokens[2][10]).toEqual value: 'translateX', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] + expect(tokens[2][16]).toEqual value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] + + describe "performance regressions", -> + it "does not hang when tokenizing invalid input preceding an equals sign", -> + grammar = atom.grammars.grammarForScopeName('source.css') + start = Date.now() + grammar.tokenizeLine(' + start = Date.now() + grammar.tokenizeLines """ + + [}~#{'ÁÂÃÄÅÆÇÈÊËÍÎ'.repeat(100)} + + """ + expect(Date.now() - start).toBeLessThan(5000) + + describe "firstLineMatch", -> + it "recognises Emacs modelines", -> + valid = """ + #-*- CSS -*- + #-*- mode: CSS -*- + /* -*-css-*- */ + // -*- CSS -*- + /* -*- mode:CSS -*- */ + // -*- font:bar;mode:CSS -*- + // -*- font:bar;mode:CSS;foo:bar; -*- + // -*-font:mode;mode:CSS-*- + // -*- foo:bar mode: css bar:baz -*- + " -*-foo:bar;mode:css;bar:foo-*- "; + " -*-font-mode:foo;mode:css;foo-bar:quux-*-" + "-*-font:x;foo:bar; mode : CsS; bar:foo;foooooo:baaaaar;fo:ba;-*-"; + "-*- font:x;foo : bar ; mode : cSS ; bar : foo ; foooooo:baaaaar;fo:ba-*-"; + """ + for line in valid.split /\n/ + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() + + invalid = """ + /* --*css-*- */ + /* -*-- CSS -*- + /* -*- -- CSS -*- + /* -*- CSS -;- -*- + // -*- CCSS -*- + // -*- CSS; -*- + // -*- css-stuff -*- + /* -*- model:css -*- + /* -*- indent-mode:css -*- + // -*- font:mode;CSS -*- + // -*- mode: -*- CSS + // -*- mode: I-miss-plain-old-css -*- + // -*-font:mode;mode:css--*- + """ + for line in invalid.split /\n/ + expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() + + it "recognises Vim modelines", -> + valid = """ + vim: se filetype=css: + # vim: se ft=css: + # vim: set ft=CSS: + # vim: set filetype=CSS: + # vim: ft=CSS + # vim: syntax=CSS + # vim: se syntax=css: + # ex: syntax=CSS + # vim:ft=css + # vim600: ft=css + # vim>600: set ft=css: + # vi:noai:sw=3 ts=6 ft=CSS + # vi::::::::::noai:::::::::::: ft=CSS + # vim:ts=4:sts=4:sw=4:noexpandtab:ft=cSS + # vi:: noai : : : : sw =3 ts =6 ft =Css + # vim: ts=4: pi sts=4: ft=CSS: noexpandtab: sw=4: + # vim: ts=4 sts=4: ft=css noexpandtab: + # vim:noexpandtab sts=4 ft=css ts=4 + # vim:noexpandtab:ft=css + # vim:ts=4:sts=4 ft=css:noexpandtab:\x20 + # vim:noexpandtab titlestring=hi\|there\\\\ ft=css ts=4 + """ + for line in valid.split /\n/ + expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() + + invalid = """ + ex: se filetype=css: + _vi: se filetype=CSS: + vi: se filetype=CSS + # vim set ft=css3 + # vim: soft=css + # vim: clean-syntax=css: + # vim set ft=css: + # vim: setft=CSS: + # vim: se ft=css backupdir=tmp + # vim: set ft=css set cmdheight=1 + # vim:noexpandtab sts:4 ft:CSS ts:4 + # vim:noexpandtab titlestring=hi\\|there\\ ft=CSS ts=4 + # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=CSS ts=4 + """ + for line in invalid.split /\n/ + expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() + + describe "Missing supported properties regressions", -> + it "recognises place-items property as supported", -> + tokens = grammar.tokenizeLines 'a { place-items: center center; }' + expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][4]).toEqual value: 'place-items', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it "recognises place-self property as supported", -> + tokens = grammar.tokenizeLines 'a { place-self: center center; }' + expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][4]).toEqual value: 'place-self', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it "recognises place-content property as supported", -> + tokens = grammar.tokenizeLines 'a { place-content: center center; }' + expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][4]).toEqual value: 'place-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] + expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] + expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] + + it "recognises row-gap property as supported", -> + tokens = grammar.tokenizeLines 'a { row-gap: 5px; }' + expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] + expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] + expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] + expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][4]).toEqual value: 'row-gap', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] + expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] + expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][7]).toEqual value: '5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] + expect(tokens[0][8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] + expect(tokens[0][9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] + expect(tokens[0][10]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] + expect(tokens[0][11]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] diff --git a/packages/language-css/spec/css-spec.js b/packages/language-css/spec/css-spec.js index 20f1373cf0..c092ee0070 100644 --- a/packages/language-css/spec/css-spec.js +++ b/packages/language-css/spec/css-spec.js @@ -1,4 +1,10 @@ - +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ describe('CSS grammar', function() { let grammar = null; @@ -7,36 +13,36 @@ describe('CSS grammar', function() { waitsForPromise(() => atom.packages.activatePackage('language-css')); - runs(() => grammar = atom.grammars.grammarForScopeName('source.css')); + return runs(() => grammar = atom.grammars.grammarForScopeName('source.css')); }); it('parses the grammar', function() { expect(grammar).toBeTruthy(); - expect(grammar.scopeName).toBe('source.css'); + return expect(grammar.scopeName).toBe('source.css'); }); describe('selectors', function() { it('tokenizes type selectors', function() { const {tokens} = grammar.tokenizeLine('p {}'); - expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + return expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); }); it('tokenizes the universal selector', function() { const {tokens} = grammar.tokenizeLine('*'); - expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + return expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); }); it('tokenises combinators', function() { const {tokens} = grammar.tokenizeLine('a > b + * ~ :not(.nah)'); expect(tokens[2]).toEqual({value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); expect(tokens[6]).toEqual({value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); - expect(tokens[10]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + return expect(tokens[10]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); }); it('highlights deprecated combinators', function() { const {tokens} = grammar.tokenizeLine('.sooo /deep/ >>>_.>>>'); expect(tokens[3]).toEqual({value: '/deep/', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); - expect(tokens[5]).toEqual({value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); + return expect(tokens[5]).toEqual({value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); }); it('tokenizes complex selectors', function() { @@ -123,41 +129,41 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(lines[4][12]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[4][13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); expect(lines[4][15]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - expect(lines[4][17]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[4][17]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); describe('custom elements (as type selectors)', function() { it('only tokenizes identifiers beginning with [a-z]', function() { const {tokens} = grammar.tokenizeLine('pearl-1941 1941-pearl -pearl-1941'); expect(tokens[0]).toEqual({value: 'pearl-1941', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); - expect(tokens[1]).toEqual({value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css']}); + return expect(tokens[1]).toEqual({value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css']}); }); it('tokenizes custom elements containing non-ASCII letters', function() { const {tokens} = grammar.tokenizeLine('pokémon-ピカチュウ'); - expect(tokens[0]).toEqual({value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + return expect(tokens[0]).toEqual({value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); }); it('does not tokenize identifiers containing [A-Z]', function() { const {tokens} = grammar.tokenizeLine('Basecamp-schedule basecamp-Schedule'); - expect(tokens[0]).toEqual({value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css']}); + return expect(tokens[0]).toEqual({value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css']}); }); it('does not tokenize identifiers containing no hyphens', function() { const {tokens} = grammar.tokenizeLine('halo_night'); - expect(tokens[0]).toEqual({value: 'halo_night', scopes: ['source.css', 'meta.selector.css']}); + return expect(tokens[0]).toEqual({value: 'halo_night', scopes: ['source.css', 'meta.selector.css']}); }); it('does not tokenise identifiers following an @ symbol', function() { const {tokens} = grammar.tokenizeLine('@some-weird-new-feature'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); - expect(tokens[1]).toEqual({value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + return expect(tokens[1]).toEqual({value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); }); - it('does not tokenise identifiers in unfamiliar functions', function() { + return it('does not tokenise identifiers in unfamiliar functions', function() { const {tokens} = grammar.tokenizeLine('some-edgy-new-function()'); expect(tokens[0]).toEqual({value: 'some-edgy-new-function(', scopes: ['source.css', 'meta.selector.css']}); - expect(tokens[1]).toEqual({value: ')', scopes: ['source.css']}); + return expect(tokens[1]).toEqual({value: ')', scopes: ['source.css']}); }); }); @@ -166,7 +172,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], const {tokens} = grammar.tokenizeLine('[title]'); expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[1]).toEqual({value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - expect(tokens[2]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[2]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes attribute selectors with identifier values', function() { @@ -175,7 +181,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[1]).toEqual({value: 'hreflang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[2]).toEqual({value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); expect(tokens[3]).toEqual({value: 'fr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); - expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes attribute selectors with string values', function() { @@ -186,7 +192,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'http://www.w3.org/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names with wildcard prefix', function() { @@ -195,7 +201,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[1]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); expect(tokens[2]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); expect(tokens[3]).toEqual({value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names with namespace prefix', function() { @@ -206,7 +212,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: 'origin', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[4]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); expect(tokens[5]).toEqual({value: 'radiation', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); - expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names without namespace prefix', function() { @@ -218,7 +224,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[5]).toEqual({value: '75', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises compound ID/attribute selectors', function() { @@ -235,7 +241,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[2]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); expect(tokens[3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[4]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); - expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + return expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); }); it('tokenises compound class/attribute selectors', function() { @@ -253,7 +259,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(tokens[4]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('allows whitespace to be inserted between tokens', function() { @@ -270,7 +276,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[10]).toEqual({value: '%%', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[11]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[12]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - expect(tokens[13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences inside attribute selectors', function() { @@ -280,7 +286,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: '0', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[5]).toEqual({value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); expect(tokens[6]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); - expect(tokens[10]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[10]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences inside namespace prefixes', function() { @@ -294,7 +300,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[8]).toEqual({value: 'It', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[9]).toEqual({value: '\\?', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); expect(tokens[10]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); - expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises comments inside attribute selectors', function() { @@ -305,7 +311,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[5]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises quoted strings in attribute selectors', function() { @@ -337,7 +343,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[24]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css']}); expect(tokens[25]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); expect(tokens[26]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - expect(tokens[27]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[27]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises unquoted strings in attribute selectors', function() { @@ -351,7 +357,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); expect(tokens[5]).toEqual({value: '0xDEADCAFE=|~BEEFBABE', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences in unquoted strings', function() { @@ -365,7 +371,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[12]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css']}); expect(tokens[13]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); - expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises the ignore-case modifier at the end of a selector', function() { @@ -392,10 +398,10 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[54]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[55]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); expect(tokens[56]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); - expect(tokens[57]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(tokens[57]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); - it('tokenises attribute selectors spanning multiple lines', function() { + return it('tokenises attribute selectors spanning multiple lines', function() { let lines = grammar.tokenizeLines(`\ span[ \\x20{2} @@ -449,7 +455,7 @@ i]\ expect(lines[3][0]).toEqual({value: ' |', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); expect(lines[4][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[5][0]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); - expect(lines[5][1]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + return expect(lines[5][1]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); }); @@ -461,19 +467,19 @@ i]\ ({tokens} = grammar.tokenizeLine('.スポンサー')); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - expect(tokens[1]).toEqual({value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + return expect(tokens[1]).toEqual({value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes a class selector consisting of two hypens', function() { const {tokens} = grammar.tokenizeLine('.--'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - expect(tokens[1]).toEqual({value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + return expect(tokens[1]).toEqual({value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes class selectors consisting of one (valid) character', function() { const {tokens} = grammar.tokenizeLine('._'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - expect(tokens[1]).toEqual({value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + return expect(tokens[1]).toEqual({value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenises class selectors starting with an escape sequence', function() { @@ -482,7 +488,7 @@ i]\ expect(tokens[1]).toEqual({value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css']}); expect(tokens[2]).toEqual({value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css']}); expect(tokens[3]).toEqual({value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); - expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises class selectors ending with an escape sequence', function() { @@ -492,35 +498,35 @@ i]\ expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css']}); expect(tokens[3]).toEqual({value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(tokens[4]).toEqual({value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css']}); - expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it contains unescaped ASCII punctuation or symbols other than "-" and "_"', function() { const {tokens} = grammar.tokenizeLine('.B&W{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'B&W', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it starts with ASCII digits ([0-9])', function() { const {tokens} = grammar.tokenizeLine('.666{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it starts with "-" followed by ASCII digits', function() { const {tokens} = grammar.tokenizeLine('.-911-{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); - it('marks a class invalid if it consists of only one hyphen', function() { + return it('marks a class invalid if it consists of only one hyphen', function() { const {tokens} = grammar.tokenizeLine('.-{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); }); @@ -528,53 +534,53 @@ i]\ it('tokenizes id selectors consisting of ASCII letters', function() { const {tokens} = grammar.tokenizeLine('#unicorn'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - expect(tokens[1]).toEqual({value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + return expect(tokens[1]).toEqual({value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors containing non-ASCII letters', function() { const {tokens} = grammar.tokenizeLine('#洪荒之力'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - expect(tokens[1]).toEqual({value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + return expect(tokens[1]).toEqual({value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors containing [0-9], "-", or "_"', function() { const {tokens} = grammar.tokenizeLine('#_zer0-day'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - expect(tokens[1]).toEqual({value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + return expect(tokens[1]).toEqual({value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors beginning with two hyphens', function() { const {tokens} = grammar.tokenizeLine('#--d3bug--'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - expect(tokens[1]).toEqual({value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + return expect(tokens[1]).toEqual({value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('marks an id invalid if it contains ASCII punctuation or symbols other than "-" and "_"', function() { const {tokens} = grammar.tokenizeLine('#sort!{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'sort!', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it starts with ASCII digits ([0-9])', function() { const {tokens} = grammar.tokenizeLine('#666{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it starts with "-" followed by ASCII digits', function() { const {tokens} = grammar.tokenizeLine('#-911-{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it consists of one hyphen only', function() { const {tokens} = grammar.tokenizeLine('#-{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises ID selectors starting with an escape sequence', function() { @@ -583,17 +589,17 @@ i]\ expect(tokens[1]).toEqual({value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css']}); expect(tokens[2]).toEqual({value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css']}); expect(tokens[3]).toEqual({value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); - expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); - it('tokenises ID selectors ending with an escape sequence', function() { + return it('tokenises ID selectors ending with an escape sequence', function() { const {tokens} = grammar.tokenizeLine('#la\\{tex\\} {'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css']}); expect(tokens[3]).toEqual({value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[4]).toEqual({value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css']}); - expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); }); @@ -605,7 +611,7 @@ i]\ expect(tokens[2]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[3]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises anonymous namespace prefixes', function() { @@ -637,7 +643,7 @@ i]\ expect(tokens[1]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[2]).toEqual({value: 'svg', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); expect(tokens[3]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); - expect(tokens[4]).toEqual({value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + return expect(tokens[4]).toEqual({value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); }); it('tokenises the "no-namespace" prefix', function() { @@ -645,10 +651,10 @@ i]\ expect(tokens[0]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); expect(tokens[1]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[3]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - it("doesn't tokenise prefixes without a selector", function() { + return it("doesn't tokenise prefixes without a selector", function() { let {tokens} = grammar.tokenizeLine('*| { }'); expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css']}); @@ -660,7 +666,7 @@ i]\ expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -682,10 +688,10 @@ i]\ expect(lines[0][1]).toEqual({value: ' Not the first line ', scopes: ['source.css', 'comment.block.css']}); expect(lines[0][2]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[1][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); - expect(lines[1][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + return expect(lines[1][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); }); - it('highlights invalid @charset statements', function() { + return it('highlights invalid @charset statements', function() { let lines = grammar.tokenizeLines(" @charset 'US-ASCII';"); expect(lines[0][0]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.leading-whitespace.charset.css']}); expect(lines[0][1]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); @@ -735,7 +741,7 @@ i]\ lines = grammar.tokenizeLines("@CHARSET 'US-ASCII';"); expect(lines[0][0]).toEqual({value: '@CHARSET', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-lowercase.charset.css']}); expect(lines[0][1]).toEqual({value: " 'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css']}); - expect(lines[0][2]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + return expect(lines[0][2]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); }); }); @@ -763,7 +769,7 @@ i]\ ({tokens} = grammar.tokenizeLine("@import 'file.css';")); expect(tokens[3]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css']}); - expect(tokens[5]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + return expect(tokens[5]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); }); it("doesn't let injected comments impact parameter matching", function() { @@ -787,7 +793,7 @@ i]\ expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[6]).toEqual({value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('correctly handles word boundaries', function() { @@ -803,7 +809,7 @@ i]\ expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'import-file', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); expect(tokens[2]).toEqual({value: '.css', scopes: ['source.css', 'meta.at-rule.header.css']}); - expect(tokens[3]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[3]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css']}); }); it('matches a URL that starts on the next line', function() { @@ -817,7 +823,7 @@ i]\ expect(lines[1][3]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(lines[1][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[1][5]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + return expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('matches comments inside query lists', function() { @@ -835,7 +841,7 @@ i]\ expect(tokens[13]).toEqual({value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[16]).toEqual({value: 'all', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css']}); - expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('highlights deprecated media types', function() { @@ -846,10 +852,10 @@ i]\ expect(tokens[4]).toEqual({value: 'astral.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[7]).toEqual({value: 'projection', scopes: ['source.css', 'meta.at-rule.import.css', 'invalid.deprecated.constant.media.css']}); - expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); - it('highlights media features in query lists', function() { + return it('highlights media features in query lists', function() { const {tokens} = grammar.tokenizeLine('@import url(\'landscape.css\') screen and (orientation:landscape);'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); @@ -866,7 +872,7 @@ i]\ expect(tokens[16]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.separator.key-value.css']}); expect(tokens[17]).toEqual({value: 'landscape', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.property-value.css']}); expect(tokens[18]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.end.bracket.round.css']}); - expect(tokens[19]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[19]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); }); @@ -898,7 +904,7 @@ i]\ expect(tokens[14]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + return expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights deprecated media types', function() { @@ -912,7 +918,7 @@ i]\ expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[10]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - expect(tokens[12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + return expect(tokens[12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights vendored media features', function() { @@ -962,7 +968,7 @@ i]\ expect(tokens[4]).toEqual({value: 'mso-page-size', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: 'wide', scopes: ['source.css', 'meta.at-rule.media.header.css']}); - expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + return expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); }); it('tokenises @media immediately following a closing brace', function() { @@ -992,7 +998,7 @@ i]\ expect(tokens[14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); expect(tokens[15]).toEqual({value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[17]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises level 4 media-query syntax', function() { @@ -1006,7 +1012,7 @@ i]\ expect(lines[0][6]).toEqual({value: '>=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); expect(lines[1][6]).toEqual({value: '<=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); expect(lines[2][6]).toEqual({value: '>', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); - expect(lines[3][6]).toEqual({value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); + return expect(lines[3][6]).toEqual({value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); }); it('tokenises comments between media types', function() { @@ -1029,10 +1035,10 @@ i]\ expect(tokens[19]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[20]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[21]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + return expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); - it('tokenises comments between media features', function() { + return it('tokenises comments between media features', function() { const {tokens} = grammar.tokenizeLine('@media/*=*/(max-width:/**/37.5em)/*=*/and/*=*/(/*=*/min-height/*:*/:/*=*/1.2em/*;*/){}'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); @@ -1073,7 +1079,7 @@ i]\ expect(tokens[36]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[37]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[38]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - expect(tokens[39]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + return expect(tokens[39]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); }); @@ -1141,7 +1147,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[3][23]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); expect(lines[3][24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(lines[3][26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - expect(lines[3][28]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + return expect(lines[3][28]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights invalid commas', function() { @@ -1158,7 +1164,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[3]).toEqual({value: ', ,', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css']}); expect(tokens[4]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('allows spaces inside ratio values', function() { @@ -1172,7 +1178,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[21]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); expect(tokens[22]).toEqual({value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css']}); expect(tokens[23]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); - expect(tokens[24]).toEqual({value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); + return expect(tokens[24]).toEqual({value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); }); describe('@keyframes', function() { @@ -1223,7 +1229,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[4][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(lines[4][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[4][12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + return expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1244,7 +1250,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][0]).toEqual({value: ' { Nah { margin-top: 2em; }', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css']}); expect(lines[2][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[2][1]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css']}); - expect(lines[2][3]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + return expect(lines[2][3]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); }); it('matches offset keywords case-insensitively', function() { @@ -1260,22 +1266,22 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[13]).toEqual({value: 'To', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); expect(tokens[15]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); expect(tokens[16]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + return expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); }); it('matches percentile offsets', function() { const {tokens} = grammar.tokenizeLine('@keyframes identifier { -50.2% } @keyframes ident2 { .25%}'); expect(tokens[7]).toEqual({value: '-50.2%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); - expect(tokens[18]).toEqual({value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); + return expect(tokens[18]).toEqual({value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); }); - it('highlights escape sequences inside identifiers', function() { + return it('highlights escape sequences inside identifiers', function() { const {tokens} = grammar.tokenizeLine('@keyframes A\\1F602Z'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css']}); expect(tokens[3]).toEqual({value: 'A', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); expect(tokens[4]).toEqual({value: '\\1F602', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css', 'constant.character.escape.codepoint.css']}); - expect(tokens[5]).toEqual({value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + return expect(tokens[5]).toEqual({value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); }); }); @@ -1293,7 +1299,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); expect(tokens[10]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[11]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); - expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + return expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('matches logical operators', function() { @@ -1305,7 +1311,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati ); expect(lines[0][3]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css']}); expect(lines[1][11]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css']}); - expect(lines[2][11]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); + return expect(lines[2][11]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); }); it('matches custom variables in feature queries', function() { @@ -1314,7 +1320,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[4]).toEqual({value: '--foo', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'variable.css']}); expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); expect(tokens[7]).toEqual({value: 'green', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); - expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + return expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); }); it("doesn't mistake brackets in string literals for feature queries", function() { @@ -1342,7 +1348,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][10]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[1][11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[1][13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('tokenises multiple feature queries', function() { @@ -1368,7 +1374,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[23]).toEqual({value: 'run-in', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); expect(tokens[25]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); - expect(tokens[26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + return expect(tokens[26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); }); it('embeds rulesets and other at-rules', function() { @@ -1469,7 +1475,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[13][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[13][12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); expect(lines[14][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); - expect(lines[15][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + return expect(lines[15][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1504,10 +1510,10 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][20]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css']}); expect(lines[1][21]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[1][22]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); - expect(lines[1][23]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + return expect(lines[1][23]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); - it('matches feature queries across multiple lines', function() { + return it('matches feature queries across multiple lines', function() { const lines = grammar.tokenizeLines(`\ @supports (box-shadow: 0 0 2px rgba(0,0,0,.5) inset) or @@ -1576,7 +1582,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[5][3]).toEqual({value: 'noticebox', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(lines[5][5]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); expect(lines[5][7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + return expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); }); @@ -1613,7 +1619,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[6]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it("doesn't confuse a prefix of 'url' as a function", function() { @@ -1627,7 +1633,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[8]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(tokens[9]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(tokens[11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('permits injected comments between tokens', function() { @@ -1647,7 +1653,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[13]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('allows no spaces between "@namespace" and quoted URLs', function() { @@ -1657,7 +1663,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[2]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[3]).toEqual({value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css']}); expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('tokenises escape sequences in prefixes', function() { @@ -1665,10 +1671,10 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[3]).toEqual({value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); expect(tokens[4]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css', 'constant.character.escape.css']}); expect(tokens[5]).toEqual({value: 'fix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); - expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + return expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); }); - it('allows arguments to span multiple lines', function() { + return it('allows arguments to span multiple lines', function() { let lines = grammar.tokenizeLines(`\ @namespace prefix"XML";\ @@ -1699,7 +1705,7 @@ url("http://a.bc/");\ expect(lines[4][3]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(lines[4][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[4][5]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(lines[4][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + return expect(lines[4][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); }); @@ -1712,7 +1718,7 @@ url("http://a.bc/");\ expect(tokens[3]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('allows font-feature names to start on a different line', function() { @@ -1725,7 +1731,7 @@ Font name 2 expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css']}); expect(lines[0][1]).toEqual({value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css']}); expect(lines[1][0]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); - expect(lines[2][0]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(lines[2][0]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1744,7 +1750,7 @@ Font name 2 expect(tokens[11]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css']}); expect(tokens[12]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[13]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); - expect(tokens[14]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[14]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises at-rules for feature names', function() { @@ -1805,7 +1811,7 @@ Font name 2 expect(lines[5][4]).toEqual({value: 'charvar', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); expect(lines[5][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); expect(lines[5][7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); - expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('matches feature-name rules case-insensitively', function() { @@ -1823,7 +1829,7 @@ Font name 2 expect(lines[2][1]).toEqual({value: 'anNOTatION', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css']}); expect(lines[3][1]).toEqual({value: 'styLISTic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css']}); expect(lines[4][1]).toEqual({value: 'STYLEset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css']}); - expect(lines[5][1]).toEqual({value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css']}); + return expect(lines[5][1]).toEqual({value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css']}); }); it('matches comments inside feature-name rules', function() { @@ -1853,10 +1859,10 @@ Font name 2 expect(lines[2][8]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[2][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[2][10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - it('highlights escape sequences inside feature-names', function() { + return it('highlights escape sequences inside feature-names', function() { const {tokens} = grammar.tokenizeLine('@swash{ s\\000077a\\73hy: 1; }'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css']}); @@ -1864,7 +1870,7 @@ Font name 2 expect(tokens[5]).toEqual({value: '\\000077', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css']}); expect(tokens[6]).toEqual({value: 'a', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); expect(tokens[7]).toEqual({value: '\\73', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css']}); - expect(tokens[8]).toEqual({value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + return expect(tokens[8]).toEqual({value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); }); }); @@ -1891,7 +1897,7 @@ Font name 2 expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - expect(tokens[3]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[3]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); })); describe('@counter-style', function() { @@ -1932,7 +1938,7 @@ Font name 2 expect(lines[3][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(lines[3][6]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[3][7]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); - expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1951,7 +1957,7 @@ Font name 2 expect(tokens[12]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css']}); expect(tokens[14]).toEqual({value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); - expect(tokens[17]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[17]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("allows the counter-style's name to start on a different line", function() { @@ -1962,16 +1968,16 @@ winners-list\ ); expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); expect(lines[0][1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); - expect(lines[1][0]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + return expect(lines[1][0]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); }); - it("highlights escape sequences inside the style's name", function() { + return it("highlights escape sequences inside the style's name", function() { const {tokens} = grammar.tokenizeLine('@counter-style A\\01F602z'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); expect(tokens[3]).toEqual({value: 'A', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); expect(tokens[4]).toEqual({value: '\\01F602', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css', 'constant.character.escape.codepoint.css']}); - expect(tokens[5]).toEqual({value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + return expect(tokens[5]).toEqual({value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); }); }); @@ -2022,7 +2028,7 @@ regexp("https:.*") { expect(lines[4][8]).toEqual({value: 'f00', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css']}); expect(lines[4][9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[4][11]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - expect(lines[5][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css']}); + return expect(lines[5][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css']}); })); describe('@viewport', function() { @@ -2042,7 +2048,7 @@ regexp("https:.*") { expect(tokens[15]).toEqual({value: '800', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(tokens[16]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises them across lines', function() { @@ -2070,10 +2076,10 @@ regexp("https:.*") { expect(lines[4][2]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[4][4]).toEqual({value: '0.9', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[4][5]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - it('tokenises injected comments', function() { + return it('tokenises injected comments', function() { const lines = grammar.tokenizeLines(`\ @-ms-viewport/*{*/{/* ==*/orientation: landscape; @@ -2093,11 +2099,11 @@ regexp("https:.*") { expect(lines[1][3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[1][5]).toEqual({value: 'landscape', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); - describe('unknown at-rules', function() { + return describe('unknown at-rules', function() { it('correctly parses single-line unknown at-rules closing with semicolons', function() { const lines = grammar.tokenizeLines(`\ @foo; @@ -2118,10 +2124,10 @@ regexp("https:.*") { expect(lines[3][2]).toEqual({value: ' ()', scopes: ['source.css', 'meta.at-rule.header.css']}); expect(lines[4][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); - expect(lines[4][2]).toEqual({value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css']}); + return expect(lines[4][2]).toEqual({value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css']}); }); - it('correctly parses single-line unknown at-rules closing with ;', function() { + return it('correctly parses single-line unknown at-rules closing with ;', function() { const lines = grammar.tokenizeLines(`\ @foo bar; .foo\ @@ -2130,7 +2136,7 @@ regexp("https:.*") { expect(lines[0][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); expect(lines[1][0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - expect(lines[1][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + return expect(lines[1][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); }); }); @@ -2151,7 +2157,7 @@ regexp("https:.*") { expect(lines[2][1]).toEqual({value: 'pAgE', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); expect(lines[2][4]).toEqual({value: 'fIRST', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(lines[3][1]).toEqual({value: 'NAMEspace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); - expect(lines[4][1]).toEqual({value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css']}); + return expect(lines[4][1]).toEqual({value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css']}); }); it('ignores case in property names', function() { @@ -2165,7 +2171,7 @@ a{ -MOZ-IMAGE: none; }\ expect(lines[0][3]).toEqual({value: 'COLOR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(lines[1][3]).toEqual({value: 'gRId-tEMPLaTe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(lines[2][3]).toEqual({value: 'bACkgrOUND-iMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); - expect(lines[3][3]).toEqual({value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); + return expect(lines[3][3]).toEqual({value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); }); it('ignores case in property keywords', function() { @@ -2187,7 +2193,7 @@ a{ font: HelVETica; }\ expect(lines[4][6]).toEqual({value: 'NONe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(lines[5][6]).toEqual({value: 'lOWER-lATIN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); expect(lines[6][6]).toEqual({value: '-WebkIT-foo', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); - expect(lines[7][6]).toEqual({value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + return expect(lines[7][6]).toEqual({value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); }); it('ignores case in selectors', function() { @@ -2212,7 +2218,7 @@ I::-mOZ-thing {}\ expect(lines[4][2]).toEqual({value: 'NOT', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(lines[5][0]).toEqual({value: 'I', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(lines[5][2]).toEqual({value: 'BACKDROP', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); - expect(lines[6][2]).toEqual({value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + return expect(lines[6][2]).toEqual({value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); it('ignores case in function names', function() { @@ -2234,10 +2240,10 @@ a{ content: cALc(2 + 2)}\ expect(lines[4][6]).toEqual({value: 'CoUNTer', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(lines[5][6]).toEqual({value: 'cuBIC-beZIER', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); expect(lines[6][6]).toEqual({value: 'sTePs', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); - expect(lines[7][6]).toEqual({value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); + return expect(lines[7][6]).toEqual({value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); }); - it('ignores case in unit names', function() { + return it('ignores case in unit names', function() { const lines = grammar.tokenizeLines(`\ a{width: 20EM; } a{width: 20ReM; } @@ -2255,7 +2261,7 @@ a{width: 2gRAd}\ expect(lines[3][6]).toEqual({value: 'S', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.s.css']}); expect(lines[4][5]).toEqual({value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[4][6]).toEqual({value: 'CM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css']}); - expect(lines[5][6]).toEqual({value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css']}); + return expect(lines[5][6]).toEqual({value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css']}); }); }); @@ -2264,7 +2270,7 @@ a{width: 2gRAd}\ const {tokens} = grammar.tokenizeLine('p:first-child'); expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); - expect(tokens[2]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + return expect(tokens[2]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); }); it("doesn't tokenise pseudo-classes if followed by a semicolon or closed bracket", function() { @@ -2274,7 +2280,7 @@ a{width: 2gRAd}\ expect(tokens[3]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[5]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); - expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); describe(':dir()', function() { @@ -2297,10 +2303,10 @@ a:dir(ltr ){ } expect(lines[1][3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[1][4]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); expect(lines[1][5]).toEqual({value: 'rtl', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); - expect(lines[1][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(lines[1][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); - it('allows :dir() to include comments and newlines', function() { + return it('allows :dir() to include comments and newlines', function() { const lines = grammar.tokenizeLines(`\ :DIR(/** ==*/ltr/* @@ -2317,7 +2323,7 @@ a:dir(ltr ){ } expect(lines[1][2]).toEqual({value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); expect(lines[1][3]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[2][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(lines[2][1]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(lines[2][1]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2330,15 +2336,15 @@ a:dir(ltr ){ } expect(tokens[3]).toEqual({value: 'zh-Hans-CN', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css']}); expect(tokens[4]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); expect(tokens[5]).toEqual({value: 'es-419', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css']}); - expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('does not tokenize unquoted language ranges containing asterisks', function() { const {tokens} = grammar.tokenizeLine(':lang(zh-*-CN)'); - expect(tokens[3]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css']}); + return expect(tokens[3]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css']}); }); - it('tokenizes language ranges containing asterisks quoted as strings', function() { + return it('tokenizes language ranges containing asterisks quoted as strings', function() { const {tokens} = grammar.tokenizeLine(':lang("zh-*-CN",\'*-ab-\')'); expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'support.constant.language-range.css']}); @@ -2346,7 +2352,7 @@ a:dir(ltr ){ } expect(tokens[6]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); expect(tokens[7]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[8]).toEqual({value: '*-ab-', scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'support.constant.language-range.css']}); - expect(tokens[9]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + return expect(tokens[9]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); }); }); @@ -2363,10 +2369,10 @@ a:dir(ltr ){ } expect(tokens[8]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[10]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); - expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); - it('tokenises injected comments', function() { + return it('tokenises injected comments', function() { const {tokens} = grammar.tokenizeLine('*:not(/*(*/.class-name/*)*/):not(/*b*/) {}'); expect(tokens[2]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2385,11 +2391,11 @@ a:dir(ltr ){ } expect(tokens[16]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[17]).toEqual({value: 'b', scopes: ['source.css', 'meta.selector.css', 'comment.block.css']}); expect(tokens[18]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); - describe(':nth-*()', function() { + return describe(':nth-*()', function() { it('tokenizes :nth-child()', function() { const tokens = grammar.tokenizeLines(`\ :nth-child(2n+1) @@ -2415,7 +2421,7 @@ a:dir(ltr ){ } expect(tokens[6][3]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[6][4]).toEqual({value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); expect(tokens[7][4]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); - expect(tokens[7][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); + return expect(tokens[7][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); }); it('tokenizes :nth-last-child()', function() { @@ -2434,7 +2440,7 @@ a:dir(ltr ){ } expect(tokens[1][4]).toEqual({value: '-2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[2][4]).toEqual({value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[2][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(tokens[3][3]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); + return expect(tokens[3][3]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); }); it('tokenizes :nth-of-type()', function() { @@ -2450,10 +2456,10 @@ img:nth-of-type(n+1)\ expect(tokens[0][4]).toEqual({value: '+n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[0][5]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[1][4]).toEqual({value: '-n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); - expect(tokens[2][4]).toEqual({value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + return expect(tokens[2][4]).toEqual({value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); }); - it('tokenizes ::nth-last-of-type()', function() { + return it('tokenizes ::nth-last-of-type()', function() { const tokens = grammar.tokenizeLines(`\ h1:nth-last-of-type(-1) h1:nth-last-of-type(+2) @@ -2466,7 +2472,7 @@ h1:nth-last-of-type(3)\ expect(tokens[0][4]).toEqual({value: '-1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[0][5]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[1][4]).toEqual({value: '+2', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); - expect(tokens[2][4]).toEqual({value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + return expect(tokens[2][4]).toEqual({value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); }); }); }); @@ -2483,7 +2489,7 @@ h1:nth-last-of-type(3)\ ({tokens} = grammar.tokenizeLine('q::after')); expect(tokens[0]).toEqual({value: 'q', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - expect(tokens[2]).toEqual({value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + return expect(tokens[2]).toEqual({value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); it('tokenizes both : and :: notations for vendor-prefixed pseudo-elements', function() { @@ -2493,39 +2499,39 @@ h1:nth-last-of-type(3)\ ({tokens} = grammar.tokenizeLine('::-webkit-input-placeholder')); expect(tokens[0]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - expect(tokens[1]).toEqual({value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + return expect(tokens[1]).toEqual({value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); - it('only tokenizes the :: notation for other pseudo-elements', function() { + return it('only tokenizes the :: notation for other pseudo-elements', function() { let {tokens} = grammar.tokenizeLine('::selection'); expect(tokens[0]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); ({tokens} = grammar.tokenizeLine(':selection')); - expect(tokens[0]).toEqual({value: ':selection', scopes: ['source.css', 'meta.selector.css']}); + return expect(tokens[0]).toEqual({value: ':selection', scopes: ['source.css', 'meta.selector.css']}); }); }); - describe('compound selectors', function() { + return describe('compound selectors', function() { it('tokenizes the combination of type selectors followed by class selectors', function() { const {tokens} = grammar.tokenizeLine('very-custom.class'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - expect(tokens[2]).toEqual({value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + return expect(tokens[2]).toEqual({value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes the combination of type selectors followed by pseudo-classes', function() { const {tokens} = grammar.tokenizeLine('very-custom:hover'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); - expect(tokens[2]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + return expect(tokens[2]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); }); - it('tokenizes the combination of type selectors followed by pseudo-elements', function() { + return it('tokenizes the combination of type selectors followed by pseudo-elements', function() { const {tokens} = grammar.tokenizeLine('very-custom::shadow'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - expect(tokens[2]).toEqual({value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + return expect(tokens[2]).toEqual({value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); }); }); @@ -2538,7 +2544,7 @@ h1:nth-last-of-type(3)\ expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes compact inline property lists', function() { @@ -2550,7 +2556,7 @@ h1:nth-last-of-type(3)\ expect(tokens[6]).toEqual({value: 'float', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(tokens[7]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[8]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); - expect(tokens[9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes multiple inline property lists', function() { @@ -2572,17 +2578,17 @@ another-one { display : none ; }\ expect(tokens[1][8]).toEqual({value: 'none', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[1][9]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[1][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(tokens[1][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[1][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes custom properties', function() { const {tokens} = grammar.tokenizeLine(':root { --white: #FFF; }'); - expect(tokens[5]).toEqual({value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css']}); + return expect(tokens[5]).toEqual({value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css']}); }); it('tokenises commas between property values', function() { const {tokens} = grammar.tokenizeLine('a{ text-shadow: a, b; }'); - expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + return expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); }); it('tokenises superfluous semicolons', function() { @@ -2595,13 +2601,13 @@ another-one { display : none ; }\ expect(lines[0][i+9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[1][i]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); } - expect(lines[1][9]).toEqual({value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + return expect(lines[1][9]).toEqual({value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); }); - describe('values', function() { + return describe('values', function() { it('tokenizes color keywords', function() { const {tokens} = grammar.tokenizeLine('#jon { color: snow; }'); - expect(tokens[8]).toEqual({value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css']}); + return expect(tokens[8]).toEqual({value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css']}); }); it('tokenises RGBA values in hex notation', function() { @@ -2622,25 +2628,25 @@ another-one { display : none ; }\ expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); ({tokens} = grammar.tokenizeLine('a{ color: #CAFEBABEF; }')); - expect(tokens[6]).toEqual({value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + return expect(tokens[6]).toEqual({value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); }); it('tokenizes common font names', function() { const {tokens} = grammar.tokenizeLine('p { font-family: Verdana, Helvetica, sans-serif; }'); expect(tokens[7]).toEqual({value: 'Verdana', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); expect(tokens[10]).toEqual({value: 'Helvetica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); - expect(tokens[13]).toEqual({value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + return expect(tokens[13]).toEqual({value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); }); it('tokenizes predefined list style types', function() { const {tokens} = grammar.tokenizeLine('ol.myth { list-style-type: cjk-earthly-branch }'); - expect(tokens[9]).toEqual({value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); + return expect(tokens[9]).toEqual({value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); }); it('tokenizes numeric values', function() { const {tokens} = grammar.tokenizeLine('div { font-size: 14px; }'); expect(tokens[7]).toEqual({value: '14', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); - expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + return expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); }); it('does not tokenize invalid numeric values', function() { @@ -2648,7 +2654,7 @@ another-one { display : none ; }\ expect(tokens[7]).toEqual({value: 'test14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); ({tokens} = grammar.tokenizeLine('div { font-size: test-14px; }')); - expect(tokens[7]).toEqual({value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + return expect(tokens[7]).toEqual({value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); }); it('tokenizes vendor-prefixed values', function() { @@ -2659,12 +2665,12 @@ another-one { display : none ; }\ expect(tokens[8]).toEqual({value: '-moz-min-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); ({tokens} = grammar.tokenizeLine('.edge { display: -ms-grid; }')); - expect(tokens[8]).toEqual({value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); + return expect(tokens[8]).toEqual({value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); }); it('tokenizes custom variables', function() { const {tokens} = grammar.tokenizeLine('div { color: var(--primary-color) }'); - expect(tokens[9]).toEqual({value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); + return expect(tokens[9]).toEqual({value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); }); it('tokenises numeric values correctly', function() { @@ -2709,7 +2715,7 @@ another-one { display : none ; }\ expect(lines[11][8]).toEqual({value: '+.5E-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[11][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); expect(lines[12][8]).toEqual({value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); - expect(lines[12][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + return expect(lines[12][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); }); describe('functional notation', function() { @@ -2723,10 +2729,10 @@ another-one { display : none ; }\ expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css']}); expect(tokens[11]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.constant.property-value.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - it('matches variables', function() { + return it('matches variables', function() { const {tokens} = grammar.tokenizeLine('a{content:ATTR(VAR(--name) px, "N/A")}'); expect(tokens[4]).toEqual({value: 'ATTR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2739,7 +2745,7 @@ another-one { display : none ; }\ expect(tokens[14]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[15]).toEqual({value: 'N/A', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css']}); expect(tokens[16]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2769,7 +2775,7 @@ a{ expect(lines[3][9]).toEqual({value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); expect(lines[4][7]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(lines[4][9]).toEqual({value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); - expect(lines[4][11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + return expect(lines[4][11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); }); it('requires whitespace around + and - operators', function() { @@ -2783,7 +2789,7 @@ a{ expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[10]).toEqual({value: '--1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); expect(tokens[19]).toEqual({value: '10', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); - expect(tokens[20]).toEqual({value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); + return expect(tokens[20]).toEqual({value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); }); it('does not require whitespace around * and / operators', function() { @@ -2795,10 +2801,10 @@ a{ ({tokens} = grammar.tokenizeLine('a{ width: calc(3px/2); }')); expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[10]).toEqual({value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); - expect(tokens[11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + return expect(tokens[11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); }); - it('matches variable expansions inside calculations', function() { + return it('matches variable expansions inside calculations', function() { const {tokens} = grammar.tokenizeLine('.foo { margin-top: calc(var(--gap) + 1px); }'); expect(tokens[8]).toEqual({value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2811,7 +2817,7 @@ a{ expect(tokens[18]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[20]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -2866,7 +2872,7 @@ a{ expect(tokens[12]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); expect(tokens[13]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); expect(tokens[14]).toEqual({value: '.7', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); - expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('matches variables as colour components', function() { @@ -2876,7 +2882,7 @@ a{ expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[10]).toEqual({value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css']}); expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(tokens[12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + return expect(tokens[12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); }); it('matches comments between colour components', function() { @@ -2895,10 +2901,10 @@ a{ expect(tokens[21]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[22]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); expect(tokens[23]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(tokens[24]).toEqual({value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + return expect(tokens[24]).toEqual({value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); }); - it('allows colour components to be split across lines', function() { + return it('allows colour components to be split across lines', function() { const lines = grammar.tokenizeLines(`\ .frost{ background-color: rgba( @@ -2940,7 +2946,7 @@ a{ expect(lines[6][7]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[6][8]).toEqual({value: ' Transparency ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); expect(lines[6][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(lines[7][1]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(lines[7][1]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2967,7 +2973,7 @@ a{ expect(tokens[16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); expect(tokens[18]).toEqual({value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); expect(tokens[19]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); - expect(tokens[21]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); + return expect(tokens[21]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); }); it('tokenises radial gradients', function() { @@ -3005,7 +3011,7 @@ a{ expect(tokens[36]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); expect(tokens[41]).toEqual({value: '.3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); expect(tokens[42]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(tokens[48]).toEqual({value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + return expect(tokens[48]).toEqual({value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); }); it('matches gradients that span multiple lines with injected comments', function() { @@ -3040,7 +3046,7 @@ a{ expect(lines[3][27]).toEqual({value: '))))))))}', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); expect(lines[3][28]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[3][29]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); - expect(lines[3][30]).toEqual({value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); + return expect(lines[3][30]).toEqual({value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); }); it('highlights vendored gradient functions', function() { @@ -3076,10 +3082,10 @@ a{ expect(lines[3][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[3][10]).toEqual({value: ' For old Opera (11.1 to 12.0) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); expect(lines[3][13]).toEqual({value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); - expect(lines[3][14]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + return expect(lines[3][14]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); }); - it('highlights antique Webkit syntax as deprecated', function() { + return it('highlights antique Webkit syntax as deprecated', function() { const lines = grammar.tokenizeLines(`\ .grad { background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, @@ -3149,7 +3155,7 @@ a{ expect(lines[9][8]).toEqual({value: '150', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); expect(lines[9][54]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); expect(lines[9][55]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(lines[10][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[10][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3188,7 +3194,7 @@ a{ expect(lines[2][16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css']}); expect(lines[2][18]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); expect(lines[2][19]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); - expect(lines[2][20]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(lines[2][20]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('tokenises OpenType feature functions', function() { @@ -3235,10 +3241,10 @@ a{ expect(lines[7][9]).toEqual({value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(lines[7][10]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[7][11]).toEqual({value: 'ident2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); - expect(lines[7][12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(lines[7][12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); }); - it('tokenises image-set()', function() { + return it('tokenises image-set()', function() { const lines = grammar.tokenizeLines(`\ a{ background-image: image-set( "foo.png" 1x, @@ -3270,7 +3276,7 @@ a{ expect(lines[3][6]).toEqual({value: 'dpi', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css', 'keyword.other.unit.dpi.css']}); expect(lines[3][8]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); expect(lines[3][9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3293,10 +3299,10 @@ a{ expect(tokens[19]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css']}); expect(tokens[20]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[21]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(tokens[22]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[22]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); }); - it('highlights the "start" and "end" keywords', function() { + return it('highlights the "start" and "end" keywords', function() { const {tokens} = grammar.tokenizeLine('a{ before: steps(0, start); after: steps(1, end); }'); expect(tokens[6]).toEqual({value: 'steps', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -3304,7 +3310,7 @@ a{ expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css']}); expect(tokens[11]).toEqual({value: 'start', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(tokens[23]).toEqual({value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); + return expect(tokens[23]).toEqual({value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); }); }); @@ -3325,7 +3331,7 @@ a{ expect(tokens[5]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); expect(tokens[6]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[8]).toEqual({value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); - expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('allows injected comments', function() { @@ -3336,10 +3342,10 @@ a{ expect(tokens[10]).toEqual({value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css']}); expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[13]).toEqual({value: '--something', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); - expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + return expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); }); - it('tokenises fallback values', function() { + return it('tokenises fallback values', function() { const {tokens} = grammar.tokenizeLine('.bar{ width: var(--page-width, /*;;;);*/ 2); }'); expect(tokens[7]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); expect(tokens[8]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -3350,11 +3356,11 @@ a{ expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[16]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'constant.numeric.css']}); expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); - expect(tokens[18]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[18]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); }); }); - it('does not tokenise functions with whitespace between name and parameters', function() { + return it('does not tokenise functions with whitespace between name and parameters', function() { let {tokens} = grammar.tokenizeLine('a{ p: attr (title); }'); expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); @@ -3409,14 +3415,14 @@ a{ expect(tokens[11]).toEqual({value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[13]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(tokens[15]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[15]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); - describe('Unicode ranges', function() { + return describe('Unicode ranges', function() { it('tokenises single codepoints', function() { const {tokens} = grammar.tokenizeLine('a{ a: U+A5 }'); - expect(tokens[6]).toEqual({value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + return expect(tokens[6]).toEqual({value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); it('tokenises codepoint ranges', function() { @@ -3428,10 +3434,10 @@ a{ ({tokens} = grammar.tokenizeLine('a{ unicode-range: u+0-7F }')); expect(tokens[6]).toEqual({value: 'u+0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); - expect(tokens[8]).toEqual({value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + return expect(tokens[8]).toEqual({value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); - it('tokenises wildcard ranges', function() { + return it('tokenises wildcard ranges', function() { let {tokens} = grammar.tokenizeLine('a{ unicode-range: U+4?? }'); expect(tokens[6]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); @@ -3440,7 +3446,7 @@ a{ expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); expect(tokens[8]).toEqual({value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); - expect(tokens[11]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + return expect(tokens[11]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); }); }); @@ -3458,7 +3464,7 @@ a{ expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); - expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css']}); + return expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css']}); }); it('tokenizes escape sequences in double-quoted strings', function() { @@ -3472,7 +3478,7 @@ a{ expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); - expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css']}); + return expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css']}); }); it('tokenises escape sequences in selectors', function() { @@ -3490,7 +3496,7 @@ a{ expect(tokens[4]).toEqual({value: '\\@', scopes: ['source.css', 'constant.character.escape.css']}); expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css']}); - expect(tokens[7]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + return expect(tokens[7]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises escape sequences in property lists', function() { @@ -3500,14 +3506,14 @@ a{ expect(tokens[6]).toEqual({value: '\\64', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); expect(tokens[7]).toEqual({value: '\\74', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); expect(tokens[8]).toEqual({value: '\\68', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); - expect(tokens[9]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + return expect(tokens[9]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); }); - it('tokenises escape sequences in property values', function() { + return it('tokenises escape sequences in property values', function() { const {tokens} = grammar.tokenizeLine('a { content: \\1F764; }'); expect(tokens[7]).toEqual({value: '\\1F764', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.character.escape.codepoint.css']}); expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3521,7 +3527,7 @@ a{ ({tokens} = grammar.tokenizeLine('a{ content: "aaaa')); expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); - expect(tokens[7]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); + return expect(tokens[7]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); }); it("knows when a string is line-wrapped", function() { @@ -3555,7 +3561,7 @@ aaa'; color: red; expect(lines[2][0]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css']}); expect(lines[2][1]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); expect(lines[2][2]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(lines[2][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + return expect(lines[2][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); }); it('highlights escape sequences inside invalid strings', function() { @@ -3569,10 +3575,10 @@ aaa'; color: red; expect(tokens[6]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[7]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); expect(tokens[8]).toEqual({value: "\\'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css']}); - expect(tokens[9]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); + return expect(tokens[9]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); }); - it('highlights unclosed lines in line-wrapped strings', function() { + return it('highlights unclosed lines in line-wrapped strings', function() { const lines = grammar.tokenizeLines(`\ a{ content: "aaa\\"aa\\ @@ -3593,7 +3599,7 @@ aaaa; color: red; expect(lines[3][4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[3][6]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); expect(lines[3][7]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3637,7 +3643,7 @@ aaaa; color: red; expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[13]).toEqual({value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + return expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('tokenises comments inside @font-face statements', function() { @@ -3648,7 +3654,7 @@ aaaa; color: red; expect(tokens[3]).toEqual({value: '"{;}"', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css']}); expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes comments before media queries', function() { @@ -3658,7 +3664,7 @@ aaaa; color: red; expect(tokens[1]).toEqual({value: ' comment ', scopes: ['source.css', 'comment.block.css']}); expect(tokens[2]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[4]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); - expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + return expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); }); it('tokenizes comments after media queries', function() { @@ -3668,7 +3674,7 @@ aaaa; color: red; expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[3]).toEqual({value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); - expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + return expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); }); it('tokenizes comments inside query lists', function() { @@ -3684,7 +3690,7 @@ aaaa; color: red; expect(tokens[9]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[10]).toEqual({value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + return expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); }); it('tokenizes inline comments', function() { @@ -3700,10 +3706,10 @@ aaaa; color: red; expect(tokens[7]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[8]).toEqual({value: 'padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); expect(tokens[9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - it('tokenizes multi-line comments', function() { + return it('tokenizes multi-line comments', function() { const lines = grammar.tokenizeLines(`\ section { border:4px /*1px; @@ -3719,7 +3725,7 @@ aaaa; color: red; expect(lines[2][0]).toEqual({value: ' padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); expect(lines[2][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3732,7 +3738,7 @@ animation-name: line-scale; ` ); expect(tokens[1][4]).toEqual({value: 'orphan-black', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); - expect(tokens[2][4]).toEqual({value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + return expect(tokens[2][4]).toEqual({value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); })); describe('Transforms', () => it('tokenizes transform functions', function() { @@ -3754,7 +3760,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); expect(tokens[1][23]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[2][4]).toEqual({value: 'rotate', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); expect(tokens[2][10]).toEqual({value: 'translateX', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); - expect(tokens[2][16]).toEqual({value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); + return expect(tokens[2][16]).toEqual({value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); })); describe("performance regressions", function() { @@ -3762,10 +3768,10 @@ transform: rotate(90deg) translateX(100px) scale(1.5); grammar = atom.grammars.grammarForScopeName('source.css'); const start = Date.now(); grammar.tokenizeLine(' @@ -3773,7 +3779,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); \ ` ); - expect(Date.now() - start).toBeLessThan(5000); + return expect(Date.now() - start).toBeLessThan(5000); }); }); @@ -3823,7 +3829,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); })(); }); - it("recognises Vim modelines", function() { + return it("recognises Vim modelines", function() { let line; const valid = `\ vim: se filetype=css: @@ -3877,7 +3883,7 @@ _vi: se filetype=CSS: }); }); - describe("Missing supported properties regressions", function() { + return describe("Missing supported properties regressions", function() { it("recognises place-items property as supported", function() { const tokens = grammar.tokenizeLines('a { place-items: center center; }'); expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); @@ -3892,7 +3898,7 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("recognises place-self property as supported", function() { @@ -3909,7 +3915,7 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("recognises place-content property as supported", function() { @@ -3926,10 +3932,10 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - it("recognises row-gap property as supported", function() { + return it("recognises row-gap property as supported", function() { const tokens = grammar.tokenizeLines('a { row-gap: 5px; }'); expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.css']}); @@ -3942,7 +3948,7 @@ _vi: se filetype=CSS: expect(tokens[0][8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[0][9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][10]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - expect(tokens[0][11]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + return expect(tokens[0][11]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); }); From d13256434176b83aecb940f2cb8e67776c2570bd Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sun, 9 Jul 2023 21:43:05 -0700 Subject: [PATCH 12/18] Revert "`language-c` remove decaf suggestions" This reverts commit b40c1e3f5e6d9c3c0638fdf87a1ea36e21828472. --- packages/language-c/spec/c-spec.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/language-c/spec/c-spec.js b/packages/language-c/spec/c-spec.js index 066edf31d3..4b5f8df793 100644 --- a/packages/language-c/spec/c-spec.js +++ b/packages/language-c/spec/c-spec.js @@ -1,4 +1,11 @@ - +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md + */ let TextEditor = null; const buildTextEditor = function(params) { if (atom.workspace.buildTextEditor != null) { From 050f0c96c508e1edb1804f459f5d6d740bdaa860 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sun, 9 Jul 2023 21:43:15 -0700 Subject: [PATCH 13/18] Revert "Manual decaf `language-c`; Remove CoffeeScript" This reverts commit 39e59555e6e0be117111dda090531e5cffbd576c. --- packages/language-c/spec/c-spec.coffee | 1140 ++++++++++++++++++++++++ packages/language-c/spec/c-spec.js | 146 +-- 2 files changed, 1213 insertions(+), 73 deletions(-) create mode 100644 packages/language-c/spec/c-spec.coffee diff --git a/packages/language-c/spec/c-spec.coffee b/packages/language-c/spec/c-spec.coffee new file mode 100644 index 0000000000..63da746928 --- /dev/null +++ b/packages/language-c/spec/c-spec.coffee @@ -0,0 +1,1140 @@ +TextEditor = null +buildTextEditor = (params) -> + if atom.workspace.buildTextEditor? + atom.workspace.buildTextEditor(params) + else + TextEditor ?= require('atom').TextEditor + new TextEditor(params) + +describe "Language-C", -> + grammar = null + + beforeEach -> + atom.config.set 'core.useTreeSitterParsers', false + + waitsForPromise -> + atom.packages.activatePackage('language-c') + + describe "C", -> + beforeEach -> + grammar = atom.grammars.grammarForScopeName('source.c') + + it "parses the grammar", -> + expect(grammar).toBeTruthy() + expect(grammar.scopeName).toBe 'source.c' + + it "tokenizes punctuation", -> + {tokens} = grammar.tokenizeLine 'hi;' + expect(tokens[1]).toEqual value: ';', scopes: ['source.c', 'punctuation.terminator.statement.c'] + + {tokens} = grammar.tokenizeLine 'a[b]' + expect(tokens[1]).toEqual value: '[', scopes: ['source.c', 'punctuation.definition.begin.bracket.square.c'] + expect(tokens[3]).toEqual value: ']', scopes: ['source.c', 'punctuation.definition.end.bracket.square.c'] + + {tokens} = grammar.tokenizeLine 'a, b' + expect(tokens[1]).toEqual value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c'] + + it "tokenizes functions", -> + lines = grammar.tokenizeLines ''' + int something(int param) { + return 0; + } + ''' + expect(lines[0][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] + expect(lines[0][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] + expect(lines[0][3]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] + expect(lines[0][4]).toEqual value: 'int', scopes: ['source.c', 'meta.function.c', 'storage.type.c'] + expect(lines[0][6]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] + expect(lines[0][8]).toEqual value: '{', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] + expect(lines[1][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] + expect(lines[1][3]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] + expect(lines[2][0]).toEqual value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] + + it "tokenizes varargs ellipses", -> + {tokens} = grammar.tokenizeLine 'void function(...);' + expect(tokens[0]).toEqual value: 'void', scopes: ['source.c', 'storage.type.c'] + expect(tokens[2]).toEqual value: 'function', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] + expect(tokens[3]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] + expect(tokens[4]).toEqual value: '...', scopes: ['source.c', 'meta.function.c', 'punctuation.vararg-ellipses.c'] + expect(tokens[5]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] + + it "tokenizes various _t types", -> + {tokens} = grammar.tokenizeLine 'size_t var;' + expect(tokens[0]).toEqual value: 'size_t', scopes: ['source.c', 'support.type.sys-types.c'] + + {tokens} = grammar.tokenizeLine 'pthread_t var;' + expect(tokens[0]).toEqual value: 'pthread_t', scopes: ['source.c', 'support.type.pthread.c'] + + {tokens} = grammar.tokenizeLine 'int32_t var;' + expect(tokens[0]).toEqual value: 'int32_t', scopes: ['source.c', 'support.type.stdint.c'] + + {tokens} = grammar.tokenizeLine 'myType_t var;' + expect(tokens[0]).toEqual value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c'] + + it "tokenizes 'line continuation' character", -> + {tokens} = grammar.tokenizeLine 'ma' + '\\' + '\n' + 'in(){};' + expect(tokens[0]).toEqual value: 'ma', scopes: ['source.c'] + expect(tokens[1]).toEqual value: '\\', scopes: ['source.c', 'constant.character.escape.line-continuation.c'] + expect(tokens[3]).toEqual value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] + + describe "strings", -> + it "tokenizes them", -> + delimsByScope = + 'string.quoted.double.c': '"' + 'string.quoted.single.c': '\'' + + for scope, delim of delimsByScope + {tokens} = grammar.tokenizeLine delim + 'a' + delim + expect(tokens[0]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.begin.c'] + expect(tokens[1]).toEqual value: 'a', scopes: ['source.c', scope] + expect(tokens[2]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.end.c'] + + {tokens} = grammar.tokenizeLine delim + 'a' + '\\' + '\n' + 'b' + delim + expect(tokens[0]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.begin.c'] + expect(tokens[1]).toEqual value: 'a', scopes: ['source.c', scope] + expect(tokens[2]).toEqual value: '\\', scopes: ['source.c', scope, 'constant.character.escape.line-continuation.c'] + expect(tokens[4]).toEqual value: 'b', scopes: ['source.c', scope] + expect(tokens[5]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.end.c'] + + {tokens} = grammar.tokenizeLine '"%d"' + expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] + expect(tokens[1]).toEqual value: '%d', scopes: ['source.c', 'string.quoted.double.c', 'constant.other.placeholder.c'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] + + {tokens} = grammar.tokenizeLine '"%"' + expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] + expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c', 'invalid.illegal.placeholder.c'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] + + {tokens} = grammar.tokenizeLine '"%" PRId32' + expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] + expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] + + {tokens} = grammar.tokenizeLine '"%" SCNd32' + expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] + expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] + + describe "comments", -> + it "tokenizes them", -> + {tokens} = grammar.tokenizeLine '/**/' + expect(tokens[0]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] + expect(tokens[1]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] + + {tokens} = grammar.tokenizeLine '/* foo */' + expect(tokens[0]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] + expect(tokens[1]).toEqual value: ' foo ', scopes: ['source.c', 'comment.block.c'] + expect(tokens[2]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] + + {tokens} = grammar.tokenizeLine '*/*' + expect(tokens[0]).toEqual value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c'] + + describe "preprocessor directives", -> + it "tokenizes '#line'", -> + {tokens} = grammar.tokenizeLine '#line 151 "copy.c"' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.line.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'line', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.line.c'] + expect(tokens[3]).toEqual value: '151', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] + expect(tokens[6]).toEqual value: 'copy.c', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c'] + expect(tokens[7]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] + + it "tokenizes '#undef'", -> + {tokens} = grammar.tokenizeLine '#undef FOO' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'undef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] + expect(tokens[3]).toEqual value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + + it "tokenizes '#pragma'", -> + {tokens} = grammar.tokenizeLine '#pragma once' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'pragma', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.pragma.c'] + expect(tokens[3]).toEqual value: 'once', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] + + {tokens} = grammar.tokenizeLine '#pragma clang diagnostic ignored "-Wunused-variable"' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'pragma', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.pragma.c'] + expect(tokens[3]).toEqual value: 'clang', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] + expect(tokens[5]).toEqual value: 'diagnostic', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] + expect(tokens[7]).toEqual value: 'ignored', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] + expect(tokens[10]).toEqual value: '-Wunused-variable', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'string.quoted.double.c'] + + {tokens} = grammar.tokenizeLine '#pragma mark – Initialization' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'pragma mark', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c'] + expect(tokens[3]).toEqual value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c'] + + describe "define", -> + it "tokenizes '#define [identifier name]'", -> + {tokens} = grammar.tokenizeLine '#define _FILE_NAME_H_' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(tokens[3]).toEqual value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + + it "tokenizes '#define [identifier name] [value]'", -> + {tokens} = grammar.tokenizeLine '#define WIDTH 80' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(tokens[3]).toEqual value: 'WIDTH', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(tokens[5]).toEqual value: '80', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] + + {tokens} = grammar.tokenizeLine '#define ABC XYZ(1)' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(tokens[3]).toEqual value: 'ABC', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(tokens[4]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[5]).toEqual value: 'XYZ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'entity.name.function.c'] + expect(tokens[6]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'punctuation.section.arguments.begin.bracket.round.c'] + expect(tokens[7]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'constant.numeric.c'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c'] + + {tokens} = grammar.tokenizeLine '#define PI_PLUS_ONE (3.14 + 1)' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(tokens[3]).toEqual value: 'PI_PLUS_ONE', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(tokens[4]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[5]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(tokens[6]).toEqual value: '3.14', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] + expect(tokens[8]).toEqual value: '+', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c'] + expect(tokens[10]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] + expect(tokens[11]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] + + describe "macros", -> + it "tokenizes them", -> + {tokens} = grammar.tokenizeLine '#define INCREMENT(x) x++' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(tokens[3]).toEqual value: 'INCREMENT', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] + expect(tokens[5]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] + expect(tokens[6]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] + expect(tokens[7]).toEqual value: ' x', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[8]).toEqual value: '++', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.increment.c'] + + {tokens} = grammar.tokenizeLine '#define MULT(x, y) (x) * (y)' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(tokens[3]).toEqual value: 'MULT', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] + expect(tokens[5]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] + expect(tokens[6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] + expect(tokens[7]).toEqual value: ' y', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] + expect(tokens[9]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[10]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(tokens[11]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[12]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] + expect(tokens[13]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[14]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c'] + expect(tokens[15]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[16]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(tokens[17]).toEqual value: 'y', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[18]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] + + {tokens} = grammar.tokenizeLine '#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while ( 0 )' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(tokens[3]).toEqual value: 'SWAP', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] + expect(tokens[5]).toEqual value: 'a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] + expect(tokens[6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] + expect(tokens[7]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] + expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] + expect(tokens[10]).toEqual value: 'do', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.c'] + expect(tokens[12]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] + expect(tokens[13]).toEqual value: ' a ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] + expect(tokens[14]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] + expect(tokens[15]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] + expect(tokens[16]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] + expect(tokens[17]).toEqual value: ' b ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] + expect(tokens[18]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] + expect(tokens[19]).toEqual value: ' a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] + expect(tokens[20]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] + expect(tokens[21]).toEqual value: ' a ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] + expect(tokens[22]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] + expect(tokens[23]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] + expect(tokens[24]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] + expect(tokens[25]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] + expect(tokens[26]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] + expect(tokens[28]).toEqual value: 'while', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.c'] + expect(tokens[29]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] + expect(tokens[30]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(tokens[32]).toEqual value: '0', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] + expect(tokens[34]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] + + it "tokenizes multiline macros", -> + lines = grammar.tokenizeLines ''' + #define max(a,b) (a>b)? \\ + a:b + ''' + expect(lines[0][17]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.character.escape.line-continuation.c'] + expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.preprocessor.macro.c'] + + lines = grammar.tokenizeLines ''' + #define SWAP(a, b) { \\ + a ^= b; \\ + b ^= a; \\ + a ^= b; \\ + } + ''' + expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(lines[0][1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(lines[0][3]).toEqual value: 'SWAP', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(lines[0][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] + expect(lines[0][5]).toEqual value: 'a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] + expect(lines[0][6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] + expect(lines[0][7]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] + expect(lines[0][8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] + expect(lines[0][10]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] + expect(lines[0][12]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] + expect(lines[1][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] + expect(lines[1][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] + expect(lines[2][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] + expect(lines[2][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] + expect(lines[3][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] + expect(lines[3][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] + expect(lines[4][0]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] + + it "tokenizes complex definitions", -> + lines = grammar.tokenizeLines ''' + #define MakeHook(name) struct HOOK name = {{false, 0L}, \\ + ((HOOKF)(*HookEnt)), ID("hook")} + ''' + expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(lines[0][1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(lines[0][3]).toEqual value: 'MakeHook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(lines[0][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] + expect(lines[0][5]).toEqual value: 'name', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] + expect(lines[0][6]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] + expect(lines[0][8]).toEqual value: 'struct', scopes: ['source.c', 'meta.preprocessor.macro.c', 'storage.type.c'] + expect(lines[0][10]).toEqual value: '=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.assignment.c'] + expect(lines[0][12]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] + expect(lines[0][13]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] + expect(lines[0][14]).toEqual value: 'false', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.language.c'] + expect(lines[0][15]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] + expect(lines[0][17]).toEqual value: '0L', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.numeric.c'] + expect(lines[0][18]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] + expect(lines[0][19]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] + expect(lines[0][21]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] + expect(lines[1][0]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(lines[1][1]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(lines[1][3]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] + expect(lines[1][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(lines[1][5]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.c'] + expect(lines[1][7]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] + expect(lines[1][8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] + expect(lines[1][9]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] + expect(lines[1][11]).toEqual value: 'ID', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'entity.name.function.c'] + expect(lines[1][12]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.begin.bracket.round.c'] + expect(lines[1][13]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.begin.c"] + expect(lines[1][14]).toEqual value: 'hook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c'] + expect(lines[1][15]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.end.c"] + expect(lines[1][16]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c'] + expect(lines[1][17]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] + + describe "includes", -> + it "tokenizes '#include'", -> + {tokens} = grammar.tokenizeLine '#include ' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] + expect(tokens[3]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] + expect(tokens[4]).toEqual value: 'stdio.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] + expect(tokens[5]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] + + {tokens} = grammar.tokenizeLine '#include' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] + expect(tokens[2]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] + expect(tokens[3]).toEqual value: 'stdio.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] + expect(tokens[4]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] + + {tokens} = grammar.tokenizeLine '#include_' + expect(tokens[0]).toEqual value: '#include_', scopes: ['source.c'] + + {tokens} = grammar.tokenizeLine '#include "file"' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] + expect(tokens[4]).toEqual value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] + + it "tokenizes '#import'", -> + {tokens} = grammar.tokenizeLine '#import "file"' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'import', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] + expect(tokens[4]).toEqual value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] + + it "tokenizes '#include_next'", -> + {tokens} = grammar.tokenizeLine '#include_next "next.h"' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'include_next', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c'] + expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] + expect(tokens[4]).toEqual value: 'next.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] + expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] + + describe "diagnostics", -> + it "tokenizes '#error'", -> + {tokens} = grammar.tokenizeLine '#error "C++ compiler required."' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'error', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c'] + expect(tokens[4]).toEqual value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c'] + + it "tokenizes '#warning'", -> + {tokens} = grammar.tokenizeLine '#warning "This is a warning."' + expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c', 'punctuation.definition.directive.c'] + expect(tokens[1]).toEqual value: 'warning', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c'] + expect(tokens[4]).toEqual value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c'] + + describe "conditionals", -> + it "tokenizes if-elif-else preprocessor blocks", -> + lines = grammar.tokenizeLines ''' + #if defined(CREDIT) + credit(); + #elif defined(DEBIT) + debit(); + #else + printerror(); + #endif + ''' + expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[0][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[0][5]).toEqual value: 'CREDIT', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[1][1]).toEqual value: 'credit', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] + expect(lines[1][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] + expect(lines[1][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] + expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[2][1]).toEqual value: 'elif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[2][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[2][5]).toEqual value: 'DEBIT', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[3][1]).toEqual value: 'debit', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] + expect(lines[3][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] + expect(lines[3][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] + expect(lines[4][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[4][1]).toEqual value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[5][1]).toEqual value: 'printerror', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] + expect(lines[5][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] + expect(lines[5][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] + expect(lines[6][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[6][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + + it "tokenizes if-true-else blocks", -> + lines = grammar.tokenizeLines ''' + #if 1 + int something() { + #if 1 + return 1; + #else + return 0; + #endif + } + #else + int something() { + return 0; + } + #endif + ''' + expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[0][3]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] + expect(lines[1][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] + expect(lines[1][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] + expect(lines[2][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[2][2]).toEqual value: 'if', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[2][4]).toEqual value: '1', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'constant.numeric.c'] + expect(lines[3][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] + expect(lines[3][3]).toEqual value: '1', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] + expect(lines[4][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[4][2]).toEqual value: 'else', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[5][0]).toEqual value: ' return 0;', scopes: ['source.c', 'meta.block.c', 'comment.block.preprocessor.else-branch.in-block.c'] + expect(lines[6][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[6][2]).toEqual value: 'endif', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[8][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[8][1]).toEqual value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[9][0]).toEqual value: 'int something() {', scopes: ['source.c', 'comment.block.preprocessor.else-branch.c'] + expect(lines[12][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[12][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + + it "tokenizes if-false-else blocks", -> + lines = grammar.tokenizeLines ''' + int something() { + #if 0 + return 1; + #else + return 0; + #endif + } + ''' + expect(lines[0][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] + expect(lines[0][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] + expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[1][2]).toEqual value: 'if', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[1][4]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'constant.numeric.c'] + expect(lines[2][0]).toEqual value: ' return 1;', scopes: ['source.c', 'meta.block.c', 'comment.block.preprocessor.if-branch.in-block.c'] + expect(lines[3][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[3][2]).toEqual value: 'else', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[4][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] + expect(lines[4][3]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] + expect(lines[5][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[5][2]).toEqual value: 'endif', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + + lines = grammar.tokenizeLines ''' + #if 0 + something(); + #endif + ''' + expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[0][3]).toEqual value: '0', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] + expect(lines[1][0]).toEqual value: ' something();', scopes: ['source.c', 'comment.block.preprocessor.if-branch.c'] + expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + + it "tokenizes ifdef-elif blocks", -> + lines = grammar.tokenizeLines ''' + #ifdef __unix__ /* is defined by compilers targeting Unix systems */ + # include + #elif defined _WIN32 /* is defined by compilers targeting Windows systems */ + # include + #endif + ''' + expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[0][1]).toEqual value: 'ifdef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[0][3]).toEqual value: '__unix__', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[0][5]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] + expect(lines[0][6]).toEqual value: ' is defined by compilers targeting Unix systems ', scopes: ['source.c', 'comment.block.c'] + expect(lines[0][7]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] + expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] + expect(lines[1][2]).toEqual value: ' include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] + expect(lines[1][4]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] + expect(lines[1][5]).toEqual value: 'unistd.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] + expect(lines[1][6]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] + expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[2][1]).toEqual value: 'elif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[2][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[2][5]).toEqual value: '_WIN32', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[2][7]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] + expect(lines[2][8]).toEqual value: ' is defined by compilers targeting Windows systems ', scopes: ['source.c', 'comment.block.c'] + expect(lines[2][9]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] + expect(lines[3][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] + expect(lines[3][2]).toEqual value: ' include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] + expect(lines[3][4]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] + expect(lines[3][5]).toEqual value: 'windows.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] + expect(lines[3][6]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] + expect(lines[4][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[4][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + + it "tokenizes ifndef blocks", -> + lines = grammar.tokenizeLines ''' + #ifndef _INCL_GUARD + #define _INCL_GUARD + #endif + ''' + expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[0][1]).toEqual value: 'ifndef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[0][3]).toEqual value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] + expect(lines[1][2]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] + expect(lines[1][4]).toEqual value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] + expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + + it "highlights stray elif, else and endif usages as invalid", -> + lines = grammar.tokenizeLines ''' + #if defined SOMEMACRO + #else + #elif //elif not permitted here + #endif + #else //else without if + #endif //endif without if + ''' + expect(lines[2][0]).toEqual value: '#elif', scopes: ['source.c', 'invalid.illegal.stray-elif.c'] + expect(lines[4][0]).toEqual value: '#else', scopes: ['source.c', 'invalid.illegal.stray-else.c'] + expect(lines[5][0]).toEqual value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c'] + + it "highlights errorneous defined usage as invalid", -> + {tokens} = grammar.tokenizeLine '#if defined == VALUE' + expect(tokens[3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c'] + + it "tokenizes multi line conditional queries", -> + lines = grammar.tokenizeLines ''' + #if !defined (MACRO_A) \\ + || !defined MACRO_C + #define MACRO_A TRUE + #elif MACRO_C == (5 + 4 - /* multi line comment */ \\ + SOMEMACRO(TRUE) * 8) // single line comment + #endif + ''' + expect(lines[0][2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] + expect(lines[0][3]).toEqual value: '!', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] + expect(lines[0][7]).toEqual value: 'MACRO_A', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[0][10]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.c', 'constant.character.escape.line-continuation.c'] + expect(lines[1][1]).toEqual value: '||', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] + expect(lines[1][3]).toEqual value: '!', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] + expect(lines[1][4]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[1][6]).toEqual value: 'MACRO_C', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[3][2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] + expect(lines[3][3]).toEqual value: 'MACRO_C', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[3][5]).toEqual value: '==', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.comparison.c'] + expect(lines[3][7]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(lines[3][8]).toEqual value: '5', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] + expect(lines[3][10]).toEqual value: '+', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] + expect(lines[3][14]).toEqual value: '-', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] + expect(lines[3][16]).toEqual value: '/*', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] + expect(lines[3][17]).toEqual value: ' multi line comment ', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c'] + expect(lines[3][18]).toEqual value: '*/', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] + expect(lines[3][20]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.c', 'constant.character.escape.line-continuation.c'] + expect(lines[4][1]).toEqual value: 'SOMEMACRO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[4][3]).toEqual value: 'TRUE', scopes: ['source.c', 'meta.preprocessor.c', 'constant.language.c'] + expect(lines[4][6]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] + expect(lines[4][9]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.end.bracket.round.c'] + expect(lines[4][11]).toEqual value: '//', scopes: ['source.c', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] + expect(lines[4][12]).toEqual value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp'] + + it "tokenizes ternary operator usage in preprocessor conditionals", -> + {tokens} = grammar.tokenizeLine '#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)' + expect(tokens[9]).toEqual value: '?', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c'] + expect(tokens[11]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(tokens[17]).toEqual value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c'] + + describe "indentation", -> + editor = null + + beforeEach -> + editor = buildTextEditor() + editor.setGrammar(grammar) + + expectPreservedIndentation = (text) -> + editor.setText(text) + editor.autoIndentBufferRows(0, editor.getLineCount() - 1) + + expectedLines = text.split('\n') + actualLines = editor.getText().split('\n') + for actualLine, i in actualLines + expect([ + actualLine, + editor.indentLevelForLine(actualLine) + ]).toEqual([ + expectedLines[i], + editor.indentLevelForLine(expectedLines[i]) + ]) + + it "indents allman-style curly braces", -> + expectPreservedIndentation ''' + if (a) + { + for (;;) + { + do + { + while (b) + { + c(); + } + } + while (d) + } + } + ''' + + it "indents non-allman-style curly braces", -> + expectPreservedIndentation ''' + if (a) { + for (;;) { + do { + while (b) { + c(); + } + } while (d) + } + } + ''' + + it "indents function arguments", -> + expectPreservedIndentation ''' + a( + b, + c( + d + ) + ); + ''' + + it "indents array and struct literals", -> + expectPreservedIndentation ''' + some_t a[3] = { + { .b = c }, + { .b = c, .d = {1, 2} }, + }; + ''' + + it "tokenizes binary literal", -> + {tokens} = grammar.tokenizeLine '0b101010' + expect(tokens[0]).toEqual value: '0b101010', scopes: ['source.c', 'constant.numeric.c'] + + describe "access", -> + it "tokenizes the dot access operator", -> + lines = grammar.tokenizeLines ''' + { + a. + } + ''' + expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] + expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] + + lines = grammar.tokenizeLines ''' + { + a.b; + } + ''' + expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] + expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] + expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] + + lines = grammar.tokenizeLines ''' + { + a.b() + } + ''' + expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] + expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] + expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'meta.function-call.c', 'entity.name.function.c'] + + lines = grammar.tokenizeLines ''' + { + a. b; + } + ''' + expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] + expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] + + lines = grammar.tokenizeLines ''' + { + a .b; + } + ''' + expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] + expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] + + lines = grammar.tokenizeLines ''' + { + a . b; + } + ''' + expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] + expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] + + it "tokenizes the pointer access operator", -> + lines = grammar.tokenizeLines ''' + { + a->b; + } + ''' + expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] + expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] + + lines = grammar.tokenizeLines ''' + { + a->b() + } + ''' + expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] + expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] + + lines = grammar.tokenizeLines ''' + { + a-> b; + } + ''' + expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] + expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] + + lines = grammar.tokenizeLines ''' + { + a ->b; + } + ''' + expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] + expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] + + lines = grammar.tokenizeLines ''' + { + a -> b; + } + ''' + expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] + expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] + + lines = grammar.tokenizeLines ''' + { + a-> + } + ''' + expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] + expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] + + describe "operators", -> + it "tokenizes the sizeof operator", -> + {tokens} = grammar.tokenizeLine('sizeof unary_expression') + expect(tokens[0]).toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] + expect(tokens[1]).toEqual value: ' unary_expression', scopes: ['source.c'] + + {tokens} = grammar.tokenizeLine('sizeof (int)') + expect(tokens[0]).toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] + expect(tokens[1]).toEqual value: ' ', scopes: ['source.c'] + expect(tokens[2]).toEqual value: '(', scopes: ['source.c', 'punctuation.section.parens.begin.bracket.round.c'] + expect(tokens[3]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] + expect(tokens[4]).toEqual value: ')', scopes: ['source.c', 'punctuation.section.parens.end.bracket.round.c'] + + {tokens} = grammar.tokenizeLine('$sizeof') + expect(tokens[1]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] + + {tokens} = grammar.tokenizeLine('sizeof$') + expect(tokens[0]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] + + {tokens} = grammar.tokenizeLine('sizeof_') + expect(tokens[0]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] + + it "tokenizes the increment operator", -> + {tokens} = grammar.tokenizeLine('i++') + expect(tokens[0]).toEqual value: 'i', scopes: ['source.c'] + expect(tokens[1]).toEqual value: '++', scopes: ['source.c', 'keyword.operator.increment.c'] + + {tokens} = grammar.tokenizeLine('++i') + expect(tokens[0]).toEqual value: '++', scopes: ['source.c', 'keyword.operator.increment.c'] + expect(tokens[1]).toEqual value: 'i', scopes: ['source.c'] + + it "tokenizes the decrement operator", -> + {tokens} = grammar.tokenizeLine('i--') + expect(tokens[0]).toEqual value: 'i', scopes: ['source.c'] + expect(tokens[1]).toEqual value: '--', scopes: ['source.c', 'keyword.operator.decrement.c'] + + {tokens} = grammar.tokenizeLine('--i') + expect(tokens[0]).toEqual value: '--', scopes: ['source.c', 'keyword.operator.decrement.c'] + expect(tokens[1]).toEqual value: 'i', scopes: ['source.c'] + + it "tokenizes logical operators", -> + {tokens} = grammar.tokenizeLine('!a') + expect(tokens[0]).toEqual value: '!', scopes: ['source.c', 'keyword.operator.logical.c'] + expect(tokens[1]).toEqual value: 'a', scopes: ['source.c'] + + operators = ['&&', '||'] + for operator in operators + {tokens} = grammar.tokenizeLine('a ' + operator + ' b') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.logical.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + + it "tokenizes comparison operators", -> + operators = ['<=', '>=', '!=', '==', '<', '>' ] + + for operator in operators + {tokens} = grammar.tokenizeLine('a ' + operator + ' b') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.comparison.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + + it "tokenizes arithmetic operators", -> + operators = ['+', '-', '*', '/', '%'] + + for operator in operators + {tokens} = grammar.tokenizeLine('a ' + operator + ' b') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + + it "tokenizes ternary operators", -> + {tokens} = grammar.tokenizeLine('a ? b : c') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] + expect(tokens[2]).toEqual value: ' b ', scopes: ['source.c'] + expect(tokens[3]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] + expect(tokens[4]).toEqual value: ' c', scopes: ['source.c'] + + it "tokenizes ternary operators with member access", -> + {tokens} = grammar.tokenizeLine('a ? b.c : d') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + expect(tokens[3]).toEqual value: '.', scopes: ['source.c', 'punctuation.separator.dot-access.c'] + expect(tokens[4]).toEqual value: 'c', scopes: ['source.c', 'variable.other.member.c'] + expect(tokens[5]).toEqual value: ' ', scopes: ['source.c'] + expect(tokens[6]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] + expect(tokens[7]).toEqual value: ' d', scopes: ['source.c'] + + it "tokenizes ternary operators with pointer dereferencing", -> + {tokens} = grammar.tokenizeLine('a ? b->c : d') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + expect(tokens[3]).toEqual value: '->', scopes: ['source.c', 'punctuation.separator.pointer-access.c'] + expect(tokens[4]).toEqual value: 'c', scopes: ['source.c', 'variable.other.member.c'] + expect(tokens[5]).toEqual value: ' ', scopes: ['source.c'] + expect(tokens[6]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] + expect(tokens[7]).toEqual value: ' d', scopes: ['source.c'] + + it "tokenizes ternary operators with function invocation", -> + {tokens} = grammar.tokenizeLine('a ? f(b) : c') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] + expect(tokens[2]).toEqual value: ' ', scopes: ['source.c'] + expect(tokens[3]).toEqual value: 'f', scopes: ['source.c', 'meta.function-call.c', 'entity.name.function.c'] + expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.begin.bracket.round.c'] + expect(tokens[5]).toEqual value: 'b', scopes: ['source.c', 'meta.function-call.c'] + expect(tokens[6]).toEqual value: ')', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.end.bracket.round.c'] + expect(tokens[7]).toEqual value: ' ', scopes: ['source.c'] + expect(tokens[8]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] + expect(tokens[9]).toEqual value: ' c', scopes: ['source.c'] + + describe "bitwise", -> + it "tokenizes bitwise 'not'", -> + {tokens} = grammar.tokenizeLine('~a') + expect(tokens[0]).toEqual value: '~', scopes: ['source.c', 'keyword.operator.c'] + expect(tokens[1]).toEqual value: 'a', scopes: ['source.c'] + + it "tokenizes shift operators", -> + {tokens} = grammar.tokenizeLine('>>') + expect(tokens[0]).toEqual value: '>>', scopes: ['source.c', 'keyword.operator.bitwise.shift.c'] + + {tokens} = grammar.tokenizeLine('<<') + expect(tokens[0]).toEqual value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c'] + + it "tokenizes them", -> + operators = ['|', '^', '&'] + + for operator in operators + {tokens} = grammar.tokenizeLine('a ' + operator + ' b') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + + describe "assignment", -> + it "tokenizes the assignment operator", -> + {tokens} = grammar.tokenizeLine('a = b') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: '=', scopes: ['source.c', 'keyword.operator.assignment.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + + it "tokenizes compound assignment operators", -> + operators = ['+=', '-=', '*=', '/=', '%='] + for operator in operators + {tokens} = grammar.tokenizeLine('a ' + operator + ' b') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.assignment.compound.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + + it "tokenizes bitwise compound operators", -> + operators = ['<<=', '>>=', '&=', '^=', '|='] + for operator in operators + {tokens} = grammar.tokenizeLine('a ' + operator + ' b') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] + expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.assignment.compound.bitwise.c'] + expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] + + describe "C++", -> + beforeEach -> + grammar = atom.grammars.grammarForScopeName('source.cpp') + + it "parses the grammar", -> + expect(grammar).toBeTruthy() + expect(grammar.scopeName).toBe 'source.cpp' + + it "tokenizes this with `.this` class", -> + {tokens} = grammar.tokenizeLine 'this.x' + expect(tokens[0]).toEqual value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp'] + + it "tokenizes classes", -> + lines = grammar.tokenizeLines ''' + class Thing { + int x; + } + ''' + expect(lines[0][0]).toEqual value: 'class', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'storage.type.cpp'] + expect(lines[0][2]).toEqual value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp'] + + it "tokenizes 'extern C'", -> + lines = grammar.tokenizeLines ''' + extern "C" { + #include "legacy_C_header.h" + } + ''' + expect(lines[0][0]).toEqual value: 'extern', scopes: ['source.cpp', 'meta.extern-block.cpp', 'storage.modifier.cpp'] + expect(lines[0][2]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] + expect(lines[0][3]).toEqual value: 'C', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp'] + expect(lines[0][4]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] + expect(lines[0][6]).toEqual value: '{', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.begin.bracket.curly.c'] + expect(lines[1][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] + expect(lines[1][1]).toEqual value: 'include', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] + expect(lines[1][3]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] + expect(lines[1][4]).toEqual value: 'legacy_C_header.h', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] + expect(lines[1][5]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] + expect(lines[2][0]).toEqual value: '}', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.end.bracket.curly.c'] + + lines = grammar.tokenizeLines ''' + #ifdef __cplusplus + extern "C" { + #endif + // legacy C code here + #ifdef __cplusplus + } + #endif + ''' + expect(lines[0][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[0][1]).toEqual value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[0][3]).toEqual value: '__cplusplus', scopes: ['source.cpp', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] + expect(lines[1][0]).toEqual value: 'extern', scopes: ['source.cpp', 'meta.extern-block.cpp', 'storage.modifier.cpp'] + expect(lines[1][2]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] + expect(lines[1][3]).toEqual value: 'C', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp'] + expect(lines[1][4]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] + expect(lines[1][6]).toEqual value: '{', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.begin.bracket.curly.c'] + expect(lines[2][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[3][1]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] + expect(lines[3][2]).toEqual value: ' legacy C code here', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] + expect(lines[4][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[4][1]).toEqual value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + expect(lines[5][0]).toEqual value: '}', scopes: ['source.cpp'] + expect(lines[6][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] + expect(lines[6][1]).toEqual value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] + + it "tokenizes UTF string escapes", -> + lines = grammar.tokenizeLines ''' + string str = U"\\U01234567\\u0123\\"\\0123\\x123"; + ''' + expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] + expect(lines[0][1]).toEqual value: '=', scopes: ['source.cpp', 'keyword.operator.assignment.c'] + expect(lines[0][3]).toEqual value: 'U', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp', 'meta.encoding.cpp'] + expect(lines[0][4]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] + expect(lines[0][5]).toEqual value: '\\U01234567', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] + expect(lines[0][6]).toEqual value: '\\u0123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] + expect(lines[0][7]).toEqual value: '\\"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] + expect(lines[0][8]).toEqual value: '\\012', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] + expect(lines[0][9]).toEqual value: '3', scopes: ['source.cpp', 'string.quoted.double.cpp'] + expect(lines[0][10]).toEqual value: '\\x123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] + expect(lines[0][11]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] + expect(lines[0][12]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] + + it "tokenizes % format specifiers", -> + {tokens} = grammar.tokenizeLine '"%d"' + expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] + expect(tokens[1]).toEqual value: '%d', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.other.placeholder.c'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] + + {tokens} = grammar.tokenizeLine '"%"' + expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] + expect(tokens[1]).toEqual value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp', 'invalid.illegal.placeholder.c'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] + + {tokens} = grammar.tokenizeLine '"%" PRId32' + expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] + expect(tokens[1]).toEqual value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] + + it "tokenizes raw string literals", -> + lines = grammar.tokenizeLines ''' + string str = R"test( + this is \"a\" test 'string' + )test"; + ''' + expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] + expect(lines[0][3]).toEqual value: 'R"test(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] + expect(lines[1][0]).toEqual value: ' this is "a" test \'string\'', scopes: ['source.cpp', 'string.quoted.double.raw.cpp'] + expect(lines[2][0]).toEqual value: ')test"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] + expect(lines[2][1]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] + + it "errors on long raw string delimiters", -> + lines = grammar.tokenizeLines ''' + string str = R"01234567890123456()01234567890123456"; + ''' + expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] + expect(lines[0][3]).toEqual value: 'R"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] + expect(lines[0][4]).toEqual value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp', 'invalid.illegal.delimiter-too-long.cpp'] + expect(lines[0][5]).toEqual value: '(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] + expect(lines[0][6]).toEqual value: ')', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] + expect(lines[0][7]).toEqual value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp', 'invalid.illegal.delimiter-too-long.cpp'] + expect(lines[0][8]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] + expect(lines[0][9]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] + + it "tokenizes destructors", -> + {tokens} = grammar.tokenizeLine('~Foo() {}') + expect(tokens[0]).toEqual value: '~Foo', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'entity.name.function.cpp'] + expect(tokens[1]).toEqual value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c'] + expect(tokens[2]).toEqual value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c'] + expect(tokens[4]).toEqual value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] + expect(tokens[5]).toEqual value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] + + {tokens} = grammar.tokenizeLine('Foo::~Bar() {}') + expect(tokens[0]).toEqual value: 'Foo::~Bar', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'entity.name.function.cpp'] + expect(tokens[1]).toEqual value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c'] + expect(tokens[2]).toEqual value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c'] + expect(tokens[4]).toEqual value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] + expect(tokens[5]).toEqual value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] + + describe "digit separators", -> + it "recognizes numbers with digit separators", -> + {tokens} = grammar.tokenizeLine "1'000" + expect(tokens[0]).toEqual value: "1'000", scopes: ['source.cpp', 'constant.numeric.c'] + + {tokens} = grammar.tokenizeLine "123'456.500'000e-1'5" + expect(tokens[0]).toEqual value: "123'456.500'000e-1'5", scopes: ['source.cpp', 'constant.numeric.c'] + + {tokens} = grammar.tokenizeLine "0x1234'5678" + expect(tokens[0]).toEqual value: "0x1234'5678", scopes: ['source.cpp', 'constant.numeric.c'] + + {tokens} = grammar.tokenizeLine "0'123'456" + expect(tokens[0]).toEqual value: "0'123'456", scopes: ['source.cpp', 'constant.numeric.c'] + + {tokens} = grammar.tokenizeLine "0b1100'0011'1111'0000" + expect(tokens[0]).toEqual value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c'] + + it "does not tokenize single quotes at the beginning or end of numbers as digit separators", -> + {tokens} = grammar.tokenizeLine "'1000" + expect(tokens[0]).toEqual value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c'] + expect(tokens[1]).toEqual value: "1000", scopes: ['source.cpp', 'string.quoted.single.c'] + + {tokens} = grammar.tokenizeLine "1000'" + expect(tokens[0]).toEqual value: "1000", scopes: ['source.cpp', 'constant.numeric.c'] + expect(tokens[1]).toEqual value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c'] + + describe "comments", -> + it "tokenizes them", -> + {tokens} = grammar.tokenizeLine '// comment' + expect(tokens[0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] + expect(tokens[1]).toEqual value: ' comment', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] + + lines = grammar.tokenizeLines ''' + // separated\\ + comment + ''' + expect(lines[0][0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] + expect(lines[0][1]).toEqual value: ' separated', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] + expect(lines[0][2]).toEqual value: '\\', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'constant.character.escape.line-continuation.c'] + expect(lines[1][0]).toEqual value: 'comment', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] + + lines = grammar.tokenizeLines ''' + // The space character \x20 is used to prevent stripping trailing whitespace + // not separated\\\x20 + comment + ''' + expect(lines[1][0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] + expect(lines[1][1]).toEqual value: ' not separated\\ ', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] + expect(lines[2][0]).toEqual value: 'comment', scopes: ['source.cpp'] + + describe "operators", -> + it "tokenizes ternary operators with namespace resolution", -> + {tokens} = grammar.tokenizeLine('a ? ns::b : ns::c') + expect(tokens[0]).toEqual value: 'a ', scopes: ['source.cpp'] + expect(tokens[1]).toEqual value: '?', scopes: ['source.cpp', 'keyword.operator.ternary.c'] + expect(tokens[2]).toEqual value: ' ns', scopes: ['source.cpp'] + expect(tokens[3]).toEqual value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp'] + expect(tokens[4]).toEqual value: 'b ', scopes: ['source.cpp'] + expect(tokens[5]).toEqual value: ':', scopes: ['source.cpp', 'keyword.operator.ternary.c'] + expect(tokens[6]).toEqual value: ' ns', scopes: ['source.cpp'] + expect(tokens[7]).toEqual value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp'] + expect(tokens[8]).toEqual value: 'c', scopes: ['source.cpp'] diff --git a/packages/language-c/spec/c-spec.js b/packages/language-c/spec/c-spec.js index 4b5f8df793..73b11e3a68 100644 --- a/packages/language-c/spec/c-spec.js +++ b/packages/language-c/spec/c-spec.js @@ -32,7 +32,7 @@ describe("Language-C", function() { it("parses the grammar", function() { expect(grammar).toBeTruthy(); - expect(grammar.scopeName).toBe('source.c'); + return expect(grammar.scopeName).toBe('source.c'); }); it("tokenizes punctuation", function() { @@ -44,7 +44,7 @@ describe("Language-C", function() { expect(tokens[3]).toEqual({value: ']', scopes: ['source.c', 'punctuation.definition.end.bracket.square.c']}); ({tokens} = grammar.tokenizeLine('a, b')); - expect(tokens[1]).toEqual({value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c']}); + return expect(tokens[1]).toEqual({value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c']}); }); it("tokenizes functions", function() { @@ -62,7 +62,7 @@ int something(int param) { expect(lines[0][8]).toEqual({value: '{', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); expect(lines[1][1]).toEqual({value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c']}); expect(lines[1][3]).toEqual({value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c']}); - expect(lines[2][0]).toEqual({value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); it("tokenizes varargs ellipses", function() { @@ -71,7 +71,7 @@ int something(int param) { expect(tokens[2]).toEqual({value: 'function', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); expect(tokens[3]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); expect(tokens[4]).toEqual({value: '...', scopes: ['source.c', 'meta.function.c', 'punctuation.vararg-ellipses.c']}); - expect(tokens[5]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); + return expect(tokens[5]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); }); it("tokenizes various _t types", function() { @@ -85,14 +85,14 @@ int something(int param) { expect(tokens[0]).toEqual({value: 'int32_t', scopes: ['source.c', 'support.type.stdint.c']}); ({tokens} = grammar.tokenizeLine('myType_t var;')); - expect(tokens[0]).toEqual({value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c']}); + return expect(tokens[0]).toEqual({value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c']}); }); it("tokenizes 'line continuation' character", function() { const {tokens} = grammar.tokenizeLine("ma\\\nin(){};"); expect(tokens[0]).toEqual({value: 'ma', scopes: ['source.c']}); expect(tokens[1]).toEqual({value: '\\', scopes: ['source.c', 'constant.character.escape.line-continuation.c']}); - expect(tokens[3]).toEqual({value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + return expect(tokens[3]).toEqual({value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); }); describe("strings", () => it("tokenizes them", function() { @@ -135,7 +135,7 @@ int something(int param) { ({tokens} = grammar.tokenizeLine('"%" SCNd32')); expect(tokens[0]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); expect(tokens[1]).toEqual({value: '%', scopes: ['source.c', 'string.quoted.double.c']}); - expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + return expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); })); describe("comments", () => it("tokenizes them", function() { @@ -149,7 +149,7 @@ int something(int param) { expect(tokens[2]).toEqual({value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c']}); ({tokens} = grammar.tokenizeLine('*/*')); - expect(tokens[0]).toEqual({value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c']}); + return expect(tokens[0]).toEqual({value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c']}); })); describe("preprocessor directives", function() { @@ -160,7 +160,7 @@ int something(int param) { expect(tokens[3]).toEqual({value: '151', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); expect(tokens[6]).toEqual({value: 'copy.c', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c']}); - expect(tokens[7]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + return expect(tokens[7]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); }); it("tokenizes '#undef'", function() { @@ -168,7 +168,7 @@ int something(int param) { expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'undef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c']}); expect(tokens[2]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.c']}); - expect(tokens[3]).toEqual({value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + return expect(tokens[3]).toEqual({value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); }); it("tokenizes '#pragma'", function() { @@ -190,7 +190,7 @@ int something(int param) { ({tokens} = grammar.tokenizeLine('#pragma mark – Initialization')); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'pragma mark', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c']}); - expect(tokens[3]).toEqual({value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c']}); + return expect(tokens[3]).toEqual({value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c']}); }); describe("define", function() { @@ -198,7 +198,7 @@ int something(int param) { const {tokens} = grammar.tokenizeLine('#define _FILE_NAME_H_'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); - expect(tokens[3]).toEqual({value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + return expect(tokens[3]).toEqual({value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); }); it("tokenizes '#define [identifier name] [value]'", function() { @@ -227,10 +227,10 @@ int something(int param) { expect(tokens[6]).toEqual({value: '3.14', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); expect(tokens[8]).toEqual({value: '+', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c']}); expect(tokens[10]).toEqual({value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); - expect(tokens[11]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + return expect(tokens[11]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); }); - describe("macros", function() { + return describe("macros", function() { it("tokenizes them", function() { let {tokens} = grammar.tokenizeLine('#define INCREMENT(x) x++'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); @@ -291,7 +291,7 @@ int something(int param) { expect(tokens[29]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); expect(tokens[30]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c']}); expect(tokens[32]).toEqual({value: '0', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); - expect(tokens[34]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + return expect(tokens[34]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); }); it("tokenizes multiline macros", function() { @@ -327,10 +327,10 @@ int something(int param) { expect(lines[2][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); expect(lines[3][1]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); expect(lines[3][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); - expect(lines[4][0]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); - it("tokenizes complex definitions", function() { + return it("tokenizes complex definitions", function() { const lines = grammar.tokenizeLines(`\ #define MakeHook(name) struct HOOK name = {{false, 0L}, \\ ((HOOKF)(*HookEnt)), ID("hook")}\ @@ -366,7 +366,7 @@ int something(int param) { expect(lines[1][14]).toEqual({value: 'hook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c']}); expect(lines[1][15]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.end.c"]}); expect(lines[1][16]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c']}); - expect(lines[1][17]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + return expect(lines[1][17]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); }); }); @@ -395,7 +395,7 @@ int something(int param) { expect(tokens[1]).toEqual({value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); it("tokenizes '#import'", function() { @@ -404,16 +404,16 @@ int something(int param) { expect(tokens[1]).toEqual({value: 'import', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); - it("tokenizes '#include_next'", function() { + return it("tokenizes '#include_next'", function() { const {tokens} = grammar.tokenizeLine('#include_next "next.h"'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'include_next', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'next.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); }); @@ -422,18 +422,18 @@ int something(int param) { const {tokens} = grammar.tokenizeLine('#error "C++ compiler required."'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'error', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c']}); - expect(tokens[4]).toEqual({value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); + return expect(tokens[4]).toEqual({value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); }); - it("tokenizes '#warning'", function() { + return it("tokenizes '#warning'", function() { const {tokens} = grammar.tokenizeLine('#warning "This is a warning."'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'warning', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c']}); - expect(tokens[4]).toEqual({value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); + return expect(tokens[4]).toEqual({value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); }); }); - describe("conditionals", function() { + return describe("conditionals", function() { it("tokenizes if-elif-else preprocessor blocks", function() { const lines = grammar.tokenizeLines(`\ #if defined(CREDIT) @@ -465,7 +465,7 @@ int something(int param) { expect(lines[5][2]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); expect(lines[5][3]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); expect(lines[6][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + return expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes if-true-else blocks", function() { @@ -504,7 +504,7 @@ int something() { expect(lines[8][1]).toEqual({value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); expect(lines[9][0]).toEqual({value: 'int something() {', scopes: ['source.c', 'comment.block.preprocessor.else-branch.c']}); expect(lines[12][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - expect(lines[12][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + return expect(lines[12][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes if-false-else blocks", function() { @@ -542,7 +542,7 @@ int something() { expect(lines[0][3]).toEqual({value: '0', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); expect(lines[1][0]).toEqual({value: ' something();', scopes: ['source.c', 'comment.block.preprocessor.if-branch.c']}); expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + return expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes ifdef-elif blocks", function() { @@ -578,7 +578,7 @@ int something() { expect(lines[3][5]).toEqual({value: 'windows.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c']}); expect(lines[3][6]).toEqual({value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c']}); expect(lines[4][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - expect(lines[4][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + return expect(lines[4][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes ifndef blocks", function() { @@ -595,7 +595,7 @@ int something() { expect(lines[1][2]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); expect(lines[1][4]).toEqual({value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + return expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("highlights stray elif, else and endif usages as invalid", function() { @@ -610,12 +610,12 @@ int something() { ); expect(lines[2][0]).toEqual({value: '#elif', scopes: ['source.c', 'invalid.illegal.stray-elif.c']}); expect(lines[4][0]).toEqual({value: '#else', scopes: ['source.c', 'invalid.illegal.stray-else.c']}); - expect(lines[5][0]).toEqual({value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c']}); + return expect(lines[5][0]).toEqual({value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c']}); }); it("highlights errorneous defined usage as invalid", function() { const {tokens} = grammar.tokenizeLine('#if defined == VALUE'); - expect(tokens[3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c']}); + return expect(tokens[3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c']}); }); it("tokenizes multi line conditional queries", function() { @@ -652,14 +652,14 @@ int something() { expect(lines[4][6]).toEqual({value: '*', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c']}); expect(lines[4][9]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.end.bracket.round.c']}); expect(lines[4][11]).toEqual({value: '//', scopes: ['source.c', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); - expect(lines[4][12]).toEqual({value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp']}); + return expect(lines[4][12]).toEqual({value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp']}); }); - it("tokenizes ternary operator usage in preprocessor conditionals", function() { + return it("tokenizes ternary operator usage in preprocessor conditionals", function() { const {tokens} = grammar.tokenizeLine('#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)'); expect(tokens[9]).toEqual({value: '?', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); expect(tokens[11]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); - expect(tokens[17]).toEqual({value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); + return expect(tokens[17]).toEqual({value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); }); }); }); @@ -669,7 +669,7 @@ int something() { beforeEach(function() { editor = buildTextEditor(); - editor.setGrammar(grammar); + return editor.setGrammar(grammar); }); const expectPreservedIndentation = function(text) { @@ -678,7 +678,7 @@ int something() { const expectedLines = text.split('\n'); const actualLines = editor.getText().split('\n'); - Array.from(actualLines).map((actualLine, i) => + return Array.from(actualLines).map((actualLine, i) => expect([ actualLine, editor.indentLevelForLine(actualLine) @@ -737,9 +737,9 @@ some_t a[3] = { ` )); - it("tokenizes binary literal", function() { + return it("tokenizes binary literal", function() { const {tokens} = grammar.tokenizeLine('0b101010'); - expect(tokens[0]).toEqual({value: '0b101010', scopes: ['source.c', 'constant.numeric.c']}); + return expect(tokens[0]).toEqual({value: '0b101010', scopes: ['source.c', 'constant.numeric.c']}); }); }); @@ -799,10 +799,10 @@ some_t a[3] = { ` ); expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); - expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + return expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); }); - it("tokenizes the pointer access operator", function() { + return it("tokenizes the pointer access operator", function() { let lines = grammar.tokenizeLines(`\ { a->b; @@ -855,11 +855,11 @@ some_t a[3] = { ` ); expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.block.c']}); - expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + return expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); }); }); - describe("operators", function() { + return describe("operators", function() { it("tokenizes the sizeof operator", function() { let {tokens} = grammar.tokenizeLine('sizeof unary_expression'); expect(tokens[0]).toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); @@ -879,7 +879,7 @@ some_t a[3] = { expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); ({tokens} = grammar.tokenizeLine('sizeof_')); - expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); + return expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); }); it("tokenizes the increment operator", function() { @@ -889,7 +889,7 @@ some_t a[3] = { ({tokens} = grammar.tokenizeLine('++i')); expect(tokens[0]).toEqual({value: '++', scopes: ['source.c', 'keyword.operator.increment.c']}); - expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); + return expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); }); it("tokenizes the decrement operator", function() { @@ -899,7 +899,7 @@ some_t a[3] = { ({tokens} = grammar.tokenizeLine('--i')); expect(tokens[0]).toEqual({value: '--', scopes: ['source.c', 'keyword.operator.decrement.c']}); - expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); + return expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); }); it("tokenizes logical operators", function() { @@ -956,7 +956,7 @@ some_t a[3] = { expect(tokens[1]).toEqual({value: '?', scopes: ['source.c', 'keyword.operator.ternary.c']}); expect(tokens[2]).toEqual({value: ' b ', scopes: ['source.c']}); expect(tokens[3]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - expect(tokens[4]).toEqual({value: ' c', scopes: ['source.c']}); + return expect(tokens[4]).toEqual({value: ' c', scopes: ['source.c']}); }); it("tokenizes ternary operators with member access", function() { @@ -968,7 +968,7 @@ some_t a[3] = { expect(tokens[4]).toEqual({value: 'c', scopes: ['source.c', 'variable.other.member.c']}); expect(tokens[5]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[6]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); + return expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); }); it("tokenizes ternary operators with pointer dereferencing", function() { @@ -980,7 +980,7 @@ some_t a[3] = { expect(tokens[4]).toEqual({value: 'c', scopes: ['source.c', 'variable.other.member.c']}); expect(tokens[5]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[6]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); + return expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); }); it("tokenizes ternary operators with function invocation", function() { @@ -994,14 +994,14 @@ some_t a[3] = { expect(tokens[6]).toEqual({value: ')', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.end.bracket.round.c']}); expect(tokens[7]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[8]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - expect(tokens[9]).toEqual({value: ' c', scopes: ['source.c']}); + return expect(tokens[9]).toEqual({value: ' c', scopes: ['source.c']}); }); describe("bitwise", function() { it("tokenizes bitwise 'not'", function() { const {tokens} = grammar.tokenizeLine('~a'); expect(tokens[0]).toEqual({value: '~', scopes: ['source.c', 'keyword.operator.c']}); - expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c']}); + return expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c']}); }); it("tokenizes shift operators", function() { @@ -1009,10 +1009,10 @@ some_t a[3] = { expect(tokens[0]).toEqual({value: '>>', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); ({tokens} = grammar.tokenizeLine('<<')); - expect(tokens[0]).toEqual({value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); + return expect(tokens[0]).toEqual({value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); }); - it("tokenizes them", function() { + return it("tokenizes them", function() { const operators = ['|', '^', '&']; return (() => { @@ -1028,12 +1028,12 @@ some_t a[3] = { }); }); - describe("assignment", function() { + return describe("assignment", function() { it("tokenizes the assignment operator", function() { const {tokens} = grammar.tokenizeLine('a = b'); expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); expect(tokens[1]).toEqual({value: '=', scopes: ['source.c', 'keyword.operator.assignment.c']}); - expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); + return expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); }); it("tokenizes compound assignment operators", function() { @@ -1050,7 +1050,7 @@ some_t a[3] = { })(); }); - it("tokenizes bitwise compound operators", function() { + return it("tokenizes bitwise compound operators", function() { const operators = ['<<=', '>>=', '&=', '^=', '|=']; return (() => { const result = []; @@ -1067,17 +1067,17 @@ some_t a[3] = { }); }); - describe("C++", function() { + return describe("C++", function() { beforeEach(() => grammar = atom.grammars.grammarForScopeName('source.cpp')); it("parses the grammar", function() { expect(grammar).toBeTruthy(); - expect(grammar.scopeName).toBe('source.cpp'); + return expect(grammar.scopeName).toBe('source.cpp'); }); it("tokenizes this with `.this` class", function() { const {tokens} = grammar.tokenizeLine('this.x'); - expect(tokens[0]).toEqual({value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp']}); + return expect(tokens[0]).toEqual({value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp']}); }); it("tokenizes classes", function() { @@ -1088,7 +1088,7 @@ class Thing { ` ); expect(lines[0][0]).toEqual({value: 'class', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'storage.type.cpp']}); - expect(lines[0][2]).toEqual({value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp']}); + return expect(lines[0][2]).toEqual({value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp']}); }); it("tokenizes 'extern C'", function() { @@ -1136,7 +1136,7 @@ extern "C" { expect(lines[4][1]).toEqual({value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); expect(lines[5][0]).toEqual({value: '}', scopes: ['source.cpp']}); expect(lines[6][0]).toEqual({value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + return expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes UTF string escapes", function() { @@ -1155,7 +1155,7 @@ string str = U"\\U01234567\\u0123\\"\\0123\\x123";\ expect(lines[0][9]).toEqual({value: '3', scopes: ['source.cpp', 'string.quoted.double.cpp']}); expect(lines[0][10]).toEqual({value: '\\x123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp']}); expect(lines[0][11]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); - expect(lines[0][12]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + return expect(lines[0][12]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("tokenizes % format specifiers", function() { @@ -1172,7 +1172,7 @@ string str = U"\\U01234567\\u0123\\"\\0123\\x123";\ ({tokens} = grammar.tokenizeLine('"%" PRId32')); expect(tokens[0]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); expect(tokens[1]).toEqual({value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp']}); - expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + return expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); }); it("tokenizes raw string literals", function() { @@ -1186,7 +1186,7 @@ string str = R"test( expect(lines[0][3]).toEqual({value: 'R"test(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp']}); expect(lines[1][0]).toEqual({value: ' this is "a" test \'string\'', scopes: ['source.cpp', 'string.quoted.double.raw.cpp']}); expect(lines[2][0]).toEqual({value: ')test"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); - expect(lines[2][1]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + return expect(lines[2][1]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("errors on long raw string delimiters", function() { @@ -1201,7 +1201,7 @@ string str = R"01234567890123456()01234567890123456";\ expect(lines[0][6]).toEqual({value: ')', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); expect(lines[0][7]).toEqual({value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp', 'invalid.illegal.delimiter-too-long.cpp']}); expect(lines[0][8]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); - expect(lines[0][9]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + return expect(lines[0][9]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("tokenizes destructors", function() { @@ -1217,7 +1217,7 @@ string str = R"01234567890123456()01234567890123456";\ expect(tokens[1]).toEqual({value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c']}); expect(tokens[2]).toEqual({value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c']}); expect(tokens[4]).toEqual({value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); - expect(tokens[5]).toEqual({value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + return expect(tokens[5]).toEqual({value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); describe("digit separators", function() { @@ -1235,17 +1235,17 @@ string str = R"01234567890123456()01234567890123456";\ expect(tokens[0]).toEqual({value: "0'123'456", scopes: ['source.cpp', 'constant.numeric.c']}); ({tokens} = grammar.tokenizeLine("0b1100'0011'1111'0000")); - expect(tokens[0]).toEqual({value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c']}); + return expect(tokens[0]).toEqual({value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c']}); }); - it("does not tokenize single quotes at the beginning or end of numbers as digit separators", function() { + return it("does not tokenize single quotes at the beginning or end of numbers as digit separators", function() { let {tokens} = grammar.tokenizeLine("'1000"); expect(tokens[0]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); expect(tokens[1]).toEqual({value: "1000", scopes: ['source.cpp', 'string.quoted.single.c']}); ({tokens} = grammar.tokenizeLine("1000'")); expect(tokens[0]).toEqual({value: "1000", scopes: ['source.cpp', 'constant.numeric.c']}); - expect(tokens[1]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); + return expect(tokens[1]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); }); }); @@ -1272,10 +1272,10 @@ comment\ ); expect(lines[1][0]).toEqual({value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); expect(lines[1][1]).toEqual({value: ' not separated\\ ', scopes: ['source.cpp', 'comment.line.double-slash.cpp']}); - expect(lines[2][0]).toEqual({value: 'comment', scopes: ['source.cpp']}); + return expect(lines[2][0]).toEqual({value: 'comment', scopes: ['source.cpp']}); })); - describe("operators", () => it("tokenizes ternary operators with namespace resolution", function() { + return describe("operators", () => it("tokenizes ternary operators with namespace resolution", function() { const {tokens} = grammar.tokenizeLine('a ? ns::b : ns::c'); expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.cpp']}); expect(tokens[1]).toEqual({value: '?', scopes: ['source.cpp', 'keyword.operator.ternary.c']}); @@ -1285,7 +1285,7 @@ comment\ expect(tokens[5]).toEqual({value: ':', scopes: ['source.cpp', 'keyword.operator.ternary.c']}); expect(tokens[6]).toEqual({value: ' ns', scopes: ['source.cpp']}); expect(tokens[7]).toEqual({value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp']}); - expect(tokens[8]).toEqual({value: 'c', scopes: ['source.cpp']}); + return expect(tokens[8]).toEqual({value: 'c', scopes: ['source.cpp']}); })); }); }); From 0d97bc67f0f39764c1ec657f8aab185e6b13a1c7 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sun, 9 Jul 2023 23:23:52 -0700 Subject: [PATCH 14/18] Revert "Revert "Manual decaf `language-c`; Remove CoffeeScript"" This reverts commit 050f0c96c508e1edb1804f459f5d6d740bdaa860. --- packages/language-c/spec/c-spec.coffee | 1140 ------------------------ packages/language-c/spec/c-spec.js | 146 +-- 2 files changed, 73 insertions(+), 1213 deletions(-) delete mode 100644 packages/language-c/spec/c-spec.coffee diff --git a/packages/language-c/spec/c-spec.coffee b/packages/language-c/spec/c-spec.coffee deleted file mode 100644 index 63da746928..0000000000 --- a/packages/language-c/spec/c-spec.coffee +++ /dev/null @@ -1,1140 +0,0 @@ -TextEditor = null -buildTextEditor = (params) -> - if atom.workspace.buildTextEditor? - atom.workspace.buildTextEditor(params) - else - TextEditor ?= require('atom').TextEditor - new TextEditor(params) - -describe "Language-C", -> - grammar = null - - beforeEach -> - atom.config.set 'core.useTreeSitterParsers', false - - waitsForPromise -> - atom.packages.activatePackage('language-c') - - describe "C", -> - beforeEach -> - grammar = atom.grammars.grammarForScopeName('source.c') - - it "parses the grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe 'source.c' - - it "tokenizes punctuation", -> - {tokens} = grammar.tokenizeLine 'hi;' - expect(tokens[1]).toEqual value: ';', scopes: ['source.c', 'punctuation.terminator.statement.c'] - - {tokens} = grammar.tokenizeLine 'a[b]' - expect(tokens[1]).toEqual value: '[', scopes: ['source.c', 'punctuation.definition.begin.bracket.square.c'] - expect(tokens[3]).toEqual value: ']', scopes: ['source.c', 'punctuation.definition.end.bracket.square.c'] - - {tokens} = grammar.tokenizeLine 'a, b' - expect(tokens[1]).toEqual value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c'] - - it "tokenizes functions", -> - lines = grammar.tokenizeLines ''' - int something(int param) { - return 0; - } - ''' - expect(lines[0][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] - expect(lines[0][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[0][3]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(lines[0][4]).toEqual value: 'int', scopes: ['source.c', 'meta.function.c', 'storage.type.c'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - expect(lines[0][8]).toEqual value: '{', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[1][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] - expect(lines[1][3]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] - expect(lines[2][0]).toEqual value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - it "tokenizes varargs ellipses", -> - {tokens} = grammar.tokenizeLine 'void function(...);' - expect(tokens[0]).toEqual value: 'void', scopes: ['source.c', 'storage.type.c'] - expect(tokens[2]).toEqual value: 'function', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(tokens[4]).toEqual value: '...', scopes: ['source.c', 'meta.function.c', 'punctuation.vararg-ellipses.c'] - expect(tokens[5]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - - it "tokenizes various _t types", -> - {tokens} = grammar.tokenizeLine 'size_t var;' - expect(tokens[0]).toEqual value: 'size_t', scopes: ['source.c', 'support.type.sys-types.c'] - - {tokens} = grammar.tokenizeLine 'pthread_t var;' - expect(tokens[0]).toEqual value: 'pthread_t', scopes: ['source.c', 'support.type.pthread.c'] - - {tokens} = grammar.tokenizeLine 'int32_t var;' - expect(tokens[0]).toEqual value: 'int32_t', scopes: ['source.c', 'support.type.stdint.c'] - - {tokens} = grammar.tokenizeLine 'myType_t var;' - expect(tokens[0]).toEqual value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c'] - - it "tokenizes 'line continuation' character", -> - {tokens} = grammar.tokenizeLine 'ma' + '\\' + '\n' + 'in(){};' - expect(tokens[0]).toEqual value: 'ma', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '\\', scopes: ['source.c', 'constant.character.escape.line-continuation.c'] - expect(tokens[3]).toEqual value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - - describe "strings", -> - it "tokenizes them", -> - delimsByScope = - 'string.quoted.double.c': '"' - 'string.quoted.single.c': '\'' - - for scope, delim of delimsByScope - {tokens} = grammar.tokenizeLine delim + 'a' + delim - expect(tokens[0]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.c', scope] - expect(tokens[2]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine delim + 'a' + '\\' + '\n' + 'b' + delim - expect(tokens[0]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.c', scope] - expect(tokens[2]).toEqual value: '\\', scopes: ['source.c', scope, 'constant.character.escape.line-continuation.c'] - expect(tokens[4]).toEqual value: 'b', scopes: ['source.c', scope] - expect(tokens[5]).toEqual value: delim, scopes: ['source.c', scope, 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '"%d"' - expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: '%d', scopes: ['source.c', 'string.quoted.double.c', 'constant.other.placeholder.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '"%"' - expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c', 'invalid.illegal.placeholder.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '"%" PRId32' - expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '"%" SCNd32' - expect(tokens[0]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.c', 'string.quoted.double.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - describe "comments", -> - it "tokenizes them", -> - {tokens} = grammar.tokenizeLine '/**/' - expect(tokens[0]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(tokens[1]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - - {tokens} = grammar.tokenizeLine '/* foo */' - expect(tokens[0]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(tokens[1]).toEqual value: ' foo ', scopes: ['source.c', 'comment.block.c'] - expect(tokens[2]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - - {tokens} = grammar.tokenizeLine '*/*' - expect(tokens[0]).toEqual value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c'] - - describe "preprocessor directives", -> - it "tokenizes '#line'", -> - {tokens} = grammar.tokenizeLine '#line 151 "copy.c"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.line.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'line', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.line.c'] - expect(tokens[3]).toEqual value: '151', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c'] - expect(tokens[6]).toEqual value: 'copy.c', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c'] - - it "tokenizes '#undef'", -> - {tokens} = grammar.tokenizeLine '#undef FOO' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'undef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] - expect(tokens[3]).toEqual value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - - it "tokenizes '#pragma'", -> - {tokens} = grammar.tokenizeLine '#pragma once' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'pragma', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.pragma.c'] - expect(tokens[3]).toEqual value: 'once', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] - - {tokens} = grammar.tokenizeLine '#pragma clang diagnostic ignored "-Wunused-variable"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'pragma', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.c'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.pragma.c'] - expect(tokens[3]).toEqual value: 'clang', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] - expect(tokens[5]).toEqual value: 'diagnostic', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] - expect(tokens[7]).toEqual value: 'ignored', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'entity.other.attribute-name.pragma.preprocessor.c'] - expect(tokens[10]).toEqual value: '-Wunused-variable', scopes: ['source.c', 'meta.preprocessor.pragma.c', 'string.quoted.double.c'] - - {tokens} = grammar.tokenizeLine '#pragma mark – Initialization' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'pragma mark', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c'] - expect(tokens[3]).toEqual value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c'] - - describe "define", -> - it "tokenizes '#define [identifier name]'", -> - {tokens} = grammar.tokenizeLine '#define _FILE_NAME_H_' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - - it "tokenizes '#define [identifier name] [value]'", -> - {tokens} = grammar.tokenizeLine '#define WIDTH 80' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'WIDTH', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[5]).toEqual value: '80', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine '#define ABC XYZ(1)' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'ABC', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[5]).toEqual value: 'XYZ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'entity.name.function.c'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'punctuation.section.arguments.begin.bracket.round.c'] - expect(tokens[7]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'constant.numeric.c'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c'] - - {tokens} = grammar.tokenizeLine '#define PI_PLUS_ONE (3.14 + 1)' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'PI_PLUS_ONE', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[6]).toEqual value: '3.14', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] - expect(tokens[8]).toEqual value: '+', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c'] - expect(tokens[10]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] - - describe "macros", -> - it "tokenizes them", -> - {tokens} = grammar.tokenizeLine '#define INCREMENT(x) x++' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'INCREMENT', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(tokens[5]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(tokens[7]).toEqual value: ' x', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[8]).toEqual value: '++', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.increment.c'] - - {tokens} = grammar.tokenizeLine '#define MULT(x, y) (x) * (y)' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'MULT', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(tokens[5]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] - expect(tokens[7]).toEqual value: ' y', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(tokens[9]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[10]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[11]).toEqual value: 'x', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(tokens[13]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[14]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c'] - expect(tokens[15]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[16]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[17]).toEqual value: 'y', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] - - {tokens} = grammar.tokenizeLine '#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while ( 0 )' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(tokens[3]).toEqual value: 'SWAP', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(tokens[5]).toEqual value: 'a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] - expect(tokens[7]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(tokens[10]).toEqual value: 'do', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.c'] - expect(tokens[12]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(tokens[13]).toEqual value: ' a ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[14]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(tokens[15]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[16]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] - expect(tokens[17]).toEqual value: ' b ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[18]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(tokens[19]).toEqual value: ' a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[20]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] - expect(tokens[21]).toEqual value: ' a ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[22]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(tokens[23]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[24]).toEqual value: ';', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.terminator.statement.c'] - expect(tokens[25]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c'] - expect(tokens[26]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - expect(tokens[28]).toEqual value: 'while', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.c'] - expect(tokens[29]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c'] - expect(tokens[30]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[32]).toEqual value: '0', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c'] - expect(tokens[34]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c'] - - it "tokenizes multiline macros", -> - lines = grammar.tokenizeLines ''' - #define max(a,b) (a>b)? \\ - a:b - ''' - expect(lines[0][17]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.character.escape.line-continuation.c'] - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.preprocessor.macro.c'] - - lines = grammar.tokenizeLines ''' - #define SWAP(a, b) { \\ - a ^= b; \\ - b ^= a; \\ - a ^= b; \\ - } - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(lines[0][3]).toEqual value: 'SWAP', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(lines[0][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(lines[0][5]).toEqual value: 'a', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(lines[0][6]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c', 'punctuation.separator.parameters.c'] - expect(lines[0][7]).toEqual value: ' b', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(lines[0][8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(lines[0][10]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[0][12]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[1][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(lines[1][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[2][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(lines[2][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[3][1]).toEqual value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(lines[3][5]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[4][0]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - it "tokenizes complex definitions", -> - lines = grammar.tokenizeLines ''' - #define MakeHook(name) struct HOOK name = {{false, 0L}, \\ - ((HOOKF)(*HookEnt)), ID("hook")} - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(lines[0][3]).toEqual value: 'MakeHook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(lines[0][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.begin.c'] - expect(lines[0][5]).toEqual value: 'name', scopes: ['source.c', 'meta.preprocessor.macro.c', 'variable.parameter.preprocessor.c'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.definition.parameters.end.c'] - expect(lines[0][8]).toEqual value: 'struct', scopes: ['source.c', 'meta.preprocessor.macro.c', 'storage.type.c'] - expect(lines[0][10]).toEqual value: '=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.assignment.c'] - expect(lines[0][12]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[0][13]).toEqual value: '{', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[0][14]).toEqual value: 'false', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.language.c'] - expect(lines[0][15]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] - expect(lines[0][17]).toEqual value: '0L', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.numeric.c'] - expect(lines[0][18]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - expect(lines[0][19]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] - expect(lines[0][21]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c'] - expect(lines[1][0]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(lines[1][1]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(lines[1][3]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(lines[1][4]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(lines[1][5]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.c'] - expect(lines[1][7]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(lines[1][8]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(lines[1][9]).toEqual value: ',', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.separator.delimiter.c'] - expect(lines[1][11]).toEqual value: 'ID', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[1][12]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.begin.bracket.round.c'] - expect(lines[1][13]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.begin.c"] - expect(lines[1][14]).toEqual value: 'hook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c'] - expect(lines[1][15]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.end.c"] - expect(lines[1][16]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c'] - expect(lines[1][17]).toEqual value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - describe "includes", -> - it "tokenizes '#include'", -> - {tokens} = grammar.tokenizeLine '#include ' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(tokens[3]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[4]).toEqual value: 'stdio.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] - expect(tokens[5]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '#include' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(tokens[2]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[3]).toEqual value: 'stdio.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] - expect(tokens[4]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] - - {tokens} = grammar.tokenizeLine '#include_' - expect(tokens[0]).toEqual value: '#include_', scopes: ['source.c'] - - {tokens} = grammar.tokenizeLine '#include "file"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[4]).toEqual value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] - - it "tokenizes '#import'", -> - {tokens} = grammar.tokenizeLine '#import "file"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[4]).toEqual value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] - - it "tokenizes '#include_next'", -> - {tokens} = grammar.tokenizeLine '#include_next "next.h"' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'include_next', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] - expect(tokens[4]).toEqual value: 'next.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] - - describe "diagnostics", -> - it "tokenizes '#error'", -> - {tokens} = grammar.tokenizeLine '#error "C++ compiler required."' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'error', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c'] - expect(tokens[4]).toEqual value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c'] - - it "tokenizes '#warning'", -> - {tokens} = grammar.tokenizeLine '#warning "This is a warning."' - expect(tokens[0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c', 'punctuation.definition.directive.c'] - expect(tokens[1]).toEqual value: 'warning', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c'] - expect(tokens[4]).toEqual value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c'] - - describe "conditionals", -> - it "tokenizes if-elif-else preprocessor blocks", -> - lines = grammar.tokenizeLines ''' - #if defined(CREDIT) - credit(); - #elif defined(DEBIT) - debit(); - #else - printerror(); - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][5]).toEqual value: 'CREDIT', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[1][1]).toEqual value: 'credit', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[1][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(lines[1][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'elif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][5]).toEqual value: 'DEBIT', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[3][1]).toEqual value: 'debit', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[3][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(lines[3][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - expect(lines[4][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[4][1]).toEqual value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[5][1]).toEqual value: 'printerror', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[5][2]).toEqual value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c'] - expect(lines[5][3]).toEqual value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c'] - expect(lines[6][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[6][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes if-true-else blocks", -> - lines = grammar.tokenizeLines ''' - #if 1 - int something() { - #if 1 - return 1; - #else - return 0; - #endif - } - #else - int something() { - return 0; - } - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '1', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[1][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] - expect(lines[1][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[2][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][2]).toEqual value: 'if', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][4]).toEqual value: '1', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[3][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] - expect(lines[3][3]).toEqual value: '1', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] - expect(lines[4][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[4][2]).toEqual value: 'else', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[5][0]).toEqual value: ' return 0;', scopes: ['source.c', 'meta.block.c', 'comment.block.preprocessor.else-branch.in-block.c'] - expect(lines[6][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[6][2]).toEqual value: 'endif', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[8][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[8][1]).toEqual value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[9][0]).toEqual value: 'int something() {', scopes: ['source.c', 'comment.block.preprocessor.else-branch.c'] - expect(lines[12][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[12][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes if-false-else blocks", -> - lines = grammar.tokenizeLines ''' - int something() { - #if 0 - return 1; - #else - return 0; - #endif - } - ''' - expect(lines[0][0]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] - expect(lines[0][2]).toEqual value: 'something', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c'] - expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[1][2]).toEqual value: 'if', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[1][4]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[2][0]).toEqual value: ' return 1;', scopes: ['source.c', 'meta.block.c', 'comment.block.preprocessor.if-branch.in-block.c'] - expect(lines[3][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[3][2]).toEqual value: 'else', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[4][1]).toEqual value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c'] - expect(lines[4][3]).toEqual value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c'] - expect(lines[5][1]).toEqual value: '#', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[5][2]).toEqual value: 'endif', scopes: ['source.c', 'meta.block.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - lines = grammar.tokenizeLines ''' - #if 0 - something(); - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'if', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '0', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[1][0]).toEqual value: ' something();', scopes: ['source.c', 'comment.block.preprocessor.if-branch.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes ifdef-elif blocks", -> - lines = grammar.tokenizeLines ''' - #ifdef __unix__ /* is defined by compilers targeting Unix systems */ - # include - #elif defined _WIN32 /* is defined by compilers targeting Windows systems */ - # include - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'ifdef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '__unix__', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[0][5]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(lines[0][6]).toEqual value: ' is defined by compilers targeting Unix systems ', scopes: ['source.c', 'comment.block.c'] - expect(lines[0][7]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(lines[1][2]).toEqual value: ' include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(lines[1][4]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] - expect(lines[1][5]).toEqual value: 'unistd.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] - expect(lines[1][6]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'elif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[2][5]).toEqual value: '_WIN32', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[2][7]).toEqual value: '/*', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(lines[2][8]).toEqual value: ' is defined by compilers targeting Windows systems ', scopes: ['source.c', 'comment.block.c'] - expect(lines[2][9]).toEqual value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - expect(lines[3][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(lines[3][2]).toEqual value: ' include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(lines[3][4]).toEqual value: '<', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.begin.c'] - expect(lines[3][5]).toEqual value: 'windows.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c'] - expect(lines[3][6]).toEqual value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c'] - expect(lines[4][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[4][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes ifndef blocks", -> - lines = grammar.tokenizeLines ''' - #ifndef _INCL_GUARD - #define _INCL_GUARD - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'ifndef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[1][1]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c'] - expect(lines[1][2]).toEqual value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c'] - expect(lines[1][4]).toEqual value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "highlights stray elif, else and endif usages as invalid", -> - lines = grammar.tokenizeLines ''' - #if defined SOMEMACRO - #else - #elif //elif not permitted here - #endif - #else //else without if - #endif //endif without if - ''' - expect(lines[2][0]).toEqual value: '#elif', scopes: ['source.c', 'invalid.illegal.stray-elif.c'] - expect(lines[4][0]).toEqual value: '#else', scopes: ['source.c', 'invalid.illegal.stray-else.c'] - expect(lines[5][0]).toEqual value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c'] - - it "highlights errorneous defined usage as invalid", -> - {tokens} = grammar.tokenizeLine '#if defined == VALUE' - expect(tokens[3]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c'] - - it "tokenizes multi line conditional queries", -> - lines = grammar.tokenizeLines ''' - #if !defined (MACRO_A) \\ - || !defined MACRO_C - #define MACRO_A TRUE - #elif MACRO_C == (5 + 4 - /* multi line comment */ \\ - SOMEMACRO(TRUE) * 8) // single line comment - #endif - ''' - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] - expect(lines[0][3]).toEqual value: '!', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] - expect(lines[0][7]).toEqual value: 'MACRO_A', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[0][10]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.c', 'constant.character.escape.line-continuation.c'] - expect(lines[1][1]).toEqual value: '||', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] - expect(lines[1][3]).toEqual value: '!', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.logical.c'] - expect(lines[1][4]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[1][6]).toEqual value: 'MACRO_C', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[3][2]).toEqual value: ' ', scopes: ['source.c', 'meta.preprocessor.c'] - expect(lines[3][3]).toEqual value: 'MACRO_C', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[3][5]).toEqual value: '==', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.comparison.c'] - expect(lines[3][7]).toEqual value: '(', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(lines[3][8]).toEqual value: '5', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c'] - expect(lines[3][10]).toEqual value: '+', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] - expect(lines[3][14]).toEqual value: '-', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] - expect(lines[3][16]).toEqual value: '/*', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c', 'punctuation.definition.comment.begin.c'] - expect(lines[3][17]).toEqual value: ' multi line comment ', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c'] - expect(lines[3][18]).toEqual value: '*/', scopes: ['source.c', 'meta.preprocessor.c', 'comment.block.c', 'punctuation.definition.comment.end.c'] - expect(lines[3][20]).toEqual value: '\\', scopes: ['source.c', 'meta.preprocessor.c', 'constant.character.escape.line-continuation.c'] - expect(lines[4][1]).toEqual value: 'SOMEMACRO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[4][3]).toEqual value: 'TRUE', scopes: ['source.c', 'meta.preprocessor.c', 'constant.language.c'] - expect(lines[4][6]).toEqual value: '*', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c'] - expect(lines[4][9]).toEqual value: ')', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.end.bracket.round.c'] - expect(lines[4][11]).toEqual value: '//', scopes: ['source.c', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(lines[4][12]).toEqual value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp'] - - it "tokenizes ternary operator usage in preprocessor conditionals", -> - {tokens} = grammar.tokenizeLine '#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)' - expect(tokens[9]).toEqual value: '?', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c'] - expect(tokens[11]).toEqual value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(tokens[17]).toEqual value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c'] - - describe "indentation", -> - editor = null - - beforeEach -> - editor = buildTextEditor() - editor.setGrammar(grammar) - - expectPreservedIndentation = (text) -> - editor.setText(text) - editor.autoIndentBufferRows(0, editor.getLineCount() - 1) - - expectedLines = text.split('\n') - actualLines = editor.getText().split('\n') - for actualLine, i in actualLines - expect([ - actualLine, - editor.indentLevelForLine(actualLine) - ]).toEqual([ - expectedLines[i], - editor.indentLevelForLine(expectedLines[i]) - ]) - - it "indents allman-style curly braces", -> - expectPreservedIndentation ''' - if (a) - { - for (;;) - { - do - { - while (b) - { - c(); - } - } - while (d) - } - } - ''' - - it "indents non-allman-style curly braces", -> - expectPreservedIndentation ''' - if (a) { - for (;;) { - do { - while (b) { - c(); - } - } while (d) - } - } - ''' - - it "indents function arguments", -> - expectPreservedIndentation ''' - a( - b, - c( - d - ) - ); - ''' - - it "indents array and struct literals", -> - expectPreservedIndentation ''' - some_t a[3] = { - { .b = c }, - { .b = c, .d = {1, 2} }, - }; - ''' - - it "tokenizes binary literal", -> - {tokens} = grammar.tokenizeLine '0b101010' - expect(tokens[0]).toEqual value: '0b101010', scopes: ['source.c', 'constant.numeric.c'] - - describe "access", -> - it "tokenizes the dot access operator", -> - lines = grammar.tokenizeLines ''' - { - a. - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - - lines = grammar.tokenizeLines ''' - { - a.b; - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a.b() - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'meta.function-call.c', 'entity.name.function.c'] - - lines = grammar.tokenizeLines ''' - { - a. b; - } - ''' - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a .b; - } - ''' - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a . b; - } - ''' - expect(lines[1][1]).toEqual value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c'] - expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - it "tokenizes the pointer access operator", -> - lines = grammar.tokenizeLines ''' - { - a->b; - } - ''' - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a->b() - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - - lines = grammar.tokenizeLines ''' - { - a-> b; - } - ''' - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a ->b; - } - ''' - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - expect(lines[1][2]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a -> b; - } - ''' - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - expect(lines[1][3]).toEqual value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c'] - - lines = grammar.tokenizeLines ''' - { - a-> - } - ''' - expect(lines[1][0]).toEqual value: ' a', scopes: ['source.c', 'meta.block.c'] - expect(lines[1][1]).toEqual value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c'] - - describe "operators", -> - it "tokenizes the sizeof operator", -> - {tokens} = grammar.tokenizeLine('sizeof unary_expression') - expect(tokens[0]).toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - expect(tokens[1]).toEqual value: ' unary_expression', scopes: ['source.c'] - - {tokens} = grammar.tokenizeLine('sizeof (int)') - expect(tokens[0]).toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - expect(tokens[1]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.c', 'punctuation.section.parens.begin.bracket.round.c'] - expect(tokens[3]).toEqual value: 'int', scopes: ['source.c', 'storage.type.c'] - expect(tokens[4]).toEqual value: ')', scopes: ['source.c', 'punctuation.section.parens.end.bracket.round.c'] - - {tokens} = grammar.tokenizeLine('$sizeof') - expect(tokens[1]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - - {tokens} = grammar.tokenizeLine('sizeof$') - expect(tokens[0]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - - {tokens} = grammar.tokenizeLine('sizeof_') - expect(tokens[0]).not.toEqual value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c'] - - it "tokenizes the increment operator", -> - {tokens} = grammar.tokenizeLine('i++') - expect(tokens[0]).toEqual value: 'i', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '++', scopes: ['source.c', 'keyword.operator.increment.c'] - - {tokens} = grammar.tokenizeLine('++i') - expect(tokens[0]).toEqual value: '++', scopes: ['source.c', 'keyword.operator.increment.c'] - expect(tokens[1]).toEqual value: 'i', scopes: ['source.c'] - - it "tokenizes the decrement operator", -> - {tokens} = grammar.tokenizeLine('i--') - expect(tokens[0]).toEqual value: 'i', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '--', scopes: ['source.c', 'keyword.operator.decrement.c'] - - {tokens} = grammar.tokenizeLine('--i') - expect(tokens[0]).toEqual value: '--', scopes: ['source.c', 'keyword.operator.decrement.c'] - expect(tokens[1]).toEqual value: 'i', scopes: ['source.c'] - - it "tokenizes logical operators", -> - {tokens} = grammar.tokenizeLine('!a') - expect(tokens[0]).toEqual value: '!', scopes: ['source.c', 'keyword.operator.logical.c'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.c'] - - operators = ['&&', '||'] - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.logical.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes comparison operators", -> - operators = ['<=', '>=', '!=', '==', '<', '>' ] - - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.comparison.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes arithmetic operators", -> - operators = ['+', '-', '*', '/', '%'] - - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes ternary operators", -> - {tokens} = grammar.tokenizeLine('a ? b : c') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' b ', scopes: ['source.c'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[4]).toEqual value: ' c', scopes: ['source.c'] - - it "tokenizes ternary operators with member access", -> - {tokens} = grammar.tokenizeLine('a ? b.c : d') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - expect(tokens[3]).toEqual value: '.', scopes: ['source.c', 'punctuation.separator.dot-access.c'] - expect(tokens[4]).toEqual value: 'c', scopes: ['source.c', 'variable.other.member.c'] - expect(tokens[5]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[6]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[7]).toEqual value: ' d', scopes: ['source.c'] - - it "tokenizes ternary operators with pointer dereferencing", -> - {tokens} = grammar.tokenizeLine('a ? b->c : d') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - expect(tokens[3]).toEqual value: '->', scopes: ['source.c', 'punctuation.separator.pointer-access.c'] - expect(tokens[4]).toEqual value: 'c', scopes: ['source.c', 'variable.other.member.c'] - expect(tokens[5]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[6]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[7]).toEqual value: ' d', scopes: ['source.c'] - - it "tokenizes ternary operators with function invocation", -> - {tokens} = grammar.tokenizeLine('a ? f(b) : c') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[3]).toEqual value: 'f', scopes: ['source.c', 'meta.function-call.c', 'entity.name.function.c'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.begin.bracket.round.c'] - expect(tokens[5]).toEqual value: 'b', scopes: ['source.c', 'meta.function-call.c'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.end.bracket.round.c'] - expect(tokens[7]).toEqual value: ' ', scopes: ['source.c'] - expect(tokens[8]).toEqual value: ':', scopes: ['source.c', 'keyword.operator.ternary.c'] - expect(tokens[9]).toEqual value: ' c', scopes: ['source.c'] - - describe "bitwise", -> - it "tokenizes bitwise 'not'", -> - {tokens} = grammar.tokenizeLine('~a') - expect(tokens[0]).toEqual value: '~', scopes: ['source.c', 'keyword.operator.c'] - expect(tokens[1]).toEqual value: 'a', scopes: ['source.c'] - - it "tokenizes shift operators", -> - {tokens} = grammar.tokenizeLine('>>') - expect(tokens[0]).toEqual value: '>>', scopes: ['source.c', 'keyword.operator.bitwise.shift.c'] - - {tokens} = grammar.tokenizeLine('<<') - expect(tokens[0]).toEqual value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c'] - - it "tokenizes them", -> - operators = ['|', '^', '&'] - - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - describe "assignment", -> - it "tokenizes the assignment operator", -> - {tokens} = grammar.tokenizeLine('a = b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: '=', scopes: ['source.c', 'keyword.operator.assignment.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes compound assignment operators", -> - operators = ['+=', '-=', '*=', '/=', '%='] - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.assignment.compound.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - it "tokenizes bitwise compound operators", -> - operators = ['<<=', '>>=', '&=', '^=', '|='] - for operator in operators - {tokens} = grammar.tokenizeLine('a ' + operator + ' b') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.c'] - expect(tokens[1]).toEqual value: operator, scopes: ['source.c', 'keyword.operator.assignment.compound.bitwise.c'] - expect(tokens[2]).toEqual value: ' b', scopes: ['source.c'] - - describe "C++", -> - beforeEach -> - grammar = atom.grammars.grammarForScopeName('source.cpp') - - it "parses the grammar", -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe 'source.cpp' - - it "tokenizes this with `.this` class", -> - {tokens} = grammar.tokenizeLine 'this.x' - expect(tokens[0]).toEqual value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp'] - - it "tokenizes classes", -> - lines = grammar.tokenizeLines ''' - class Thing { - int x; - } - ''' - expect(lines[0][0]).toEqual value: 'class', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'storage.type.cpp'] - expect(lines[0][2]).toEqual value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp'] - - it "tokenizes 'extern C'", -> - lines = grammar.tokenizeLines ''' - extern "C" { - #include "legacy_C_header.h" - } - ''' - expect(lines[0][0]).toEqual value: 'extern', scopes: ['source.cpp', 'meta.extern-block.cpp', 'storage.modifier.cpp'] - expect(lines[0][2]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[0][3]).toEqual value: 'C', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp'] - expect(lines[0][4]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[0][6]).toEqual value: '{', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[1][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c', 'punctuation.definition.directive.c'] - expect(lines[1][1]).toEqual value: 'include', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c'] - expect(lines[1][3]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c'] - expect(lines[1][4]).toEqual value: 'legacy_C_header.h', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c'] - expect(lines[1][5]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c'] - expect(lines[2][0]).toEqual value: '}', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.end.bracket.curly.c'] - - lines = grammar.tokenizeLines ''' - #ifdef __cplusplus - extern "C" { - #endif - // legacy C code here - #ifdef __cplusplus - } - #endif - ''' - expect(lines[0][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[0][1]).toEqual value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[0][3]).toEqual value: '__cplusplus', scopes: ['source.cpp', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c'] - expect(lines[1][0]).toEqual value: 'extern', scopes: ['source.cpp', 'meta.extern-block.cpp', 'storage.modifier.cpp'] - expect(lines[1][2]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[1][3]).toEqual value: 'C', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp'] - expect(lines[1][4]).toEqual value: '"', scopes: ['source.cpp', 'meta.extern-block.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[1][6]).toEqual value: '{', scopes: ['source.cpp', 'meta.extern-block.cpp', 'punctuation.section.block.begin.bracket.curly.c'] - expect(lines[2][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[2][1]).toEqual value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[3][1]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(lines[3][2]).toEqual value: ' legacy C code here', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - expect(lines[4][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[4][1]).toEqual value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - expect(lines[5][0]).toEqual value: '}', scopes: ['source.cpp'] - expect(lines[6][0]).toEqual value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c'] - expect(lines[6][1]).toEqual value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c'] - - it "tokenizes UTF string escapes", -> - lines = grammar.tokenizeLines ''' - string str = U"\\U01234567\\u0123\\"\\0123\\x123"; - ''' - expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] - expect(lines[0][1]).toEqual value: '=', scopes: ['source.cpp', 'keyword.operator.assignment.c'] - expect(lines[0][3]).toEqual value: 'U', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp', 'meta.encoding.cpp'] - expect(lines[0][4]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[0][5]).toEqual value: '\\U01234567', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][6]).toEqual value: '\\u0123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][7]).toEqual value: '\\"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][8]).toEqual value: '\\012', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][9]).toEqual value: '3', scopes: ['source.cpp', 'string.quoted.double.cpp'] - expect(lines[0][10]).toEqual value: '\\x123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp'] - expect(lines[0][11]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[0][12]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] - - it "tokenizes % format specifiers", -> - {tokens} = grammar.tokenizeLine '"%d"' - expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(tokens[1]).toEqual value: '%d', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.other.placeholder.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - - {tokens} = grammar.tokenizeLine '"%"' - expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp', 'invalid.illegal.placeholder.c'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - - {tokens} = grammar.tokenizeLine '"%" PRId32' - expect(tokens[0]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp'] - expect(tokens[1]).toEqual value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp'] - - it "tokenizes raw string literals", -> - lines = grammar.tokenizeLines ''' - string str = R"test( - this is \"a\" test 'string' - )test"; - ''' - expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] - expect(lines[0][3]).toEqual value: 'R"test(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[1][0]).toEqual value: ' this is "a" test \'string\'', scopes: ['source.cpp', 'string.quoted.double.raw.cpp'] - expect(lines[2][0]).toEqual value: ')test"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[2][1]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] - - it "errors on long raw string delimiters", -> - lines = grammar.tokenizeLines ''' - string str = R"01234567890123456()01234567890123456"; - ''' - expect(lines[0][0]).toEqual value: 'string str ', scopes: ['source.cpp'] - expect(lines[0][3]).toEqual value: 'R"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[0][4]).toEqual value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp', 'invalid.illegal.delimiter-too-long.cpp'] - expect(lines[0][5]).toEqual value: '(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[0][7]).toEqual value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp', 'invalid.illegal.delimiter-too-long.cpp'] - expect(lines[0][8]).toEqual value: '"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp'] - expect(lines[0][9]).toEqual value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c'] - - it "tokenizes destructors", -> - {tokens} = grammar.tokenizeLine('~Foo() {}') - expect(tokens[0]).toEqual value: '~Foo', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'entity.name.function.cpp'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c'] - expect(tokens[2]).toEqual value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - {tokens} = grammar.tokenizeLine('Foo::~Bar() {}') - expect(tokens[0]).toEqual value: 'Foo::~Bar', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'entity.name.function.cpp'] - expect(tokens[1]).toEqual value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c'] - expect(tokens[2]).toEqual value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c'] - - describe "digit separators", -> - it "recognizes numbers with digit separators", -> - {tokens} = grammar.tokenizeLine "1'000" - expect(tokens[0]).toEqual value: "1'000", scopes: ['source.cpp', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine "123'456.500'000e-1'5" - expect(tokens[0]).toEqual value: "123'456.500'000e-1'5", scopes: ['source.cpp', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine "0x1234'5678" - expect(tokens[0]).toEqual value: "0x1234'5678", scopes: ['source.cpp', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine "0'123'456" - expect(tokens[0]).toEqual value: "0'123'456", scopes: ['source.cpp', 'constant.numeric.c'] - - {tokens} = grammar.tokenizeLine "0b1100'0011'1111'0000" - expect(tokens[0]).toEqual value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c'] - - it "does not tokenize single quotes at the beginning or end of numbers as digit separators", -> - {tokens} = grammar.tokenizeLine "'1000" - expect(tokens[0]).toEqual value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c'] - expect(tokens[1]).toEqual value: "1000", scopes: ['source.cpp', 'string.quoted.single.c'] - - {tokens} = grammar.tokenizeLine "1000'" - expect(tokens[0]).toEqual value: "1000", scopes: ['source.cpp', 'constant.numeric.c'] - expect(tokens[1]).toEqual value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c'] - - describe "comments", -> - it "tokenizes them", -> - {tokens} = grammar.tokenizeLine '// comment' - expect(tokens[0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(tokens[1]).toEqual value: ' comment', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - - lines = grammar.tokenizeLines ''' - // separated\\ - comment - ''' - expect(lines[0][0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(lines[0][1]).toEqual value: ' separated', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - expect(lines[0][2]).toEqual value: '\\', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'constant.character.escape.line-continuation.c'] - expect(lines[1][0]).toEqual value: 'comment', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - - lines = grammar.tokenizeLines ''' - // The space character \x20 is used to prevent stripping trailing whitespace - // not separated\\\x20 - comment - ''' - expect(lines[1][0]).toEqual value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp'] - expect(lines[1][1]).toEqual value: ' not separated\\ ', scopes: ['source.cpp', 'comment.line.double-slash.cpp'] - expect(lines[2][0]).toEqual value: 'comment', scopes: ['source.cpp'] - - describe "operators", -> - it "tokenizes ternary operators with namespace resolution", -> - {tokens} = grammar.tokenizeLine('a ? ns::b : ns::c') - expect(tokens[0]).toEqual value: 'a ', scopes: ['source.cpp'] - expect(tokens[1]).toEqual value: '?', scopes: ['source.cpp', 'keyword.operator.ternary.c'] - expect(tokens[2]).toEqual value: ' ns', scopes: ['source.cpp'] - expect(tokens[3]).toEqual value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp'] - expect(tokens[4]).toEqual value: 'b ', scopes: ['source.cpp'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.cpp', 'keyword.operator.ternary.c'] - expect(tokens[6]).toEqual value: ' ns', scopes: ['source.cpp'] - expect(tokens[7]).toEqual value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp'] - expect(tokens[8]).toEqual value: 'c', scopes: ['source.cpp'] diff --git a/packages/language-c/spec/c-spec.js b/packages/language-c/spec/c-spec.js index 73b11e3a68..4b5f8df793 100644 --- a/packages/language-c/spec/c-spec.js +++ b/packages/language-c/spec/c-spec.js @@ -32,7 +32,7 @@ describe("Language-C", function() { it("parses the grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe('source.c'); + expect(grammar.scopeName).toBe('source.c'); }); it("tokenizes punctuation", function() { @@ -44,7 +44,7 @@ describe("Language-C", function() { expect(tokens[3]).toEqual({value: ']', scopes: ['source.c', 'punctuation.definition.end.bracket.square.c']}); ({tokens} = grammar.tokenizeLine('a, b')); - return expect(tokens[1]).toEqual({value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c']}); + expect(tokens[1]).toEqual({value: ',', scopes: ['source.c', 'punctuation.separator.delimiter.c']}); }); it("tokenizes functions", function() { @@ -62,7 +62,7 @@ int something(int param) { expect(lines[0][8]).toEqual({value: '{', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); expect(lines[1][1]).toEqual({value: 'return', scopes: ['source.c', 'meta.block.c', 'keyword.control.c']}); expect(lines[1][3]).toEqual({value: '0', scopes: ['source.c', 'meta.block.c', 'constant.numeric.c']}); - return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(lines[2][0]).toEqual({value: '}', scopes: ['source.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); it("tokenizes varargs ellipses", function() { @@ -71,7 +71,7 @@ int something(int param) { expect(tokens[2]).toEqual({value: 'function', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); expect(tokens[3]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); expect(tokens[4]).toEqual({value: '...', scopes: ['source.c', 'meta.function.c', 'punctuation.vararg-ellipses.c']}); - return expect(tokens[5]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); + expect(tokens[5]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); }); it("tokenizes various _t types", function() { @@ -85,14 +85,14 @@ int something(int param) { expect(tokens[0]).toEqual({value: 'int32_t', scopes: ['source.c', 'support.type.stdint.c']}); ({tokens} = grammar.tokenizeLine('myType_t var;')); - return expect(tokens[0]).toEqual({value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c']}); + expect(tokens[0]).toEqual({value: 'myType_t', scopes: ['source.c', 'support.type.posix-reserved.c']}); }); it("tokenizes 'line continuation' character", function() { const {tokens} = grammar.tokenizeLine("ma\\\nin(){};"); expect(tokens[0]).toEqual({value: 'ma', scopes: ['source.c']}); expect(tokens[1]).toEqual({value: '\\', scopes: ['source.c', 'constant.character.escape.line-continuation.c']}); - return expect(tokens[3]).toEqual({value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); + expect(tokens[3]).toEqual({value: 'in', scopes: ['source.c', 'meta.function.c', 'entity.name.function.c']}); }); describe("strings", () => it("tokenizes them", function() { @@ -135,7 +135,7 @@ int something(int param) { ({tokens} = grammar.tokenizeLine('"%" SCNd32')); expect(tokens[0]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); expect(tokens[1]).toEqual({value: '%', scopes: ['source.c', 'string.quoted.double.c']}); - return expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); })); describe("comments", () => it("tokenizes them", function() { @@ -149,7 +149,7 @@ int something(int param) { expect(tokens[2]).toEqual({value: '*/', scopes: ['source.c', 'comment.block.c', 'punctuation.definition.comment.end.c']}); ({tokens} = grammar.tokenizeLine('*/*')); - return expect(tokens[0]).toEqual({value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c']}); + expect(tokens[0]).toEqual({value: '*/*', scopes: ['source.c', 'invalid.illegal.stray-comment-end.c']}); })); describe("preprocessor directives", function() { @@ -160,7 +160,7 @@ int something(int param) { expect(tokens[3]).toEqual({value: '151', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.begin.c']}); expect(tokens[6]).toEqual({value: 'copy.c', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c']}); - return expect(tokens[7]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.c', 'string.quoted.double.c', 'punctuation.definition.string.end.c']}); }); it("tokenizes '#undef'", function() { @@ -168,7 +168,7 @@ int something(int param) { expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'undef', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.undef.c']}); expect(tokens[2]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.c']}); - return expect(tokens[3]).toEqual({value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[3]).toEqual({value: 'FOO', scopes: ['source.c', 'meta.preprocessor.c', 'entity.name.function.preprocessor.c']}); }); it("tokenizes '#pragma'", function() { @@ -190,7 +190,7 @@ int something(int param) { ({tokens} = grammar.tokenizeLine('#pragma mark – Initialization')); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'pragma mark', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'keyword.control.directive.pragma.pragma-mark.c']}); - return expect(tokens[3]).toEqual({value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c']}); + expect(tokens[3]).toEqual({value: '– Initialization', scopes: ['source.c', 'meta.section', 'meta.preprocessor.pragma.c', 'entity.name.tag.pragma-mark.c']}); }); describe("define", function() { @@ -198,7 +198,7 @@ int something(int param) { const {tokens} = grammar.tokenizeLine('#define _FILE_NAME_H_'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); - return expect(tokens[3]).toEqual({value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); + expect(tokens[3]).toEqual({value: '_FILE_NAME_H_', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); }); it("tokenizes '#define [identifier name] [value]'", function() { @@ -227,10 +227,10 @@ int something(int param) { expect(tokens[6]).toEqual({value: '3.14', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); expect(tokens[8]).toEqual({value: '+', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.operator.c']}); expect(tokens[10]).toEqual({value: '1', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); - return expect(tokens[11]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(tokens[11]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); }); - return describe("macros", function() { + describe("macros", function() { it("tokenizes them", function() { let {tokens} = grammar.tokenizeLine('#define INCREMENT(x) x++'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c', 'punctuation.definition.directive.c']}); @@ -291,7 +291,7 @@ int something(int param) { expect(tokens[29]).toEqual({value: ' ', scopes: ['source.c', 'meta.preprocessor.macro.c']}); expect(tokens[30]).toEqual({value: '(', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.begin.bracket.round.c']}); expect(tokens[32]).toEqual({value: '0', scopes: ['source.c', 'meta.preprocessor.macro.c', 'constant.numeric.c']}); - return expect(tokens[34]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); + expect(tokens[34]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'punctuation.section.parens.end.bracket.round.c']}); }); it("tokenizes multiline macros", function() { @@ -327,10 +327,10 @@ int something(int param) { expect(lines[2][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); expect(lines[3][1]).toEqual({value: '^=', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'keyword.operator.assignment.compound.bitwise.c']}); expect(lines[3][5]).toEqual({value: '\\', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'constant.character.escape.line-continuation.c']}); - return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(lines[4][0]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); - return it("tokenizes complex definitions", function() { + it("tokenizes complex definitions", function() { const lines = grammar.tokenizeLines(`\ #define MakeHook(name) struct HOOK name = {{false, 0L}, \\ ((HOOKF)(*HookEnt)), ID("hook")}\ @@ -366,7 +366,7 @@ int something(int param) { expect(lines[1][14]).toEqual({value: 'hook', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c']}); expect(lines[1][15]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'string.quoted.double.c', "punctuation.definition.string.end.c"]}); expect(lines[1][16]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'meta.function.c', 'punctuation.section.arguments.end.bracket.round.c']}); - return expect(lines[1][17]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(lines[1][17]).toEqual({value: '}', scopes: ['source.c', 'meta.preprocessor.macro.c', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); }); }); @@ -395,7 +395,7 @@ int something(int param) { expect(tokens[1]).toEqual({value: 'include', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); it("tokenizes '#import'", function() { @@ -404,16 +404,16 @@ int something(int param) { expect(tokens[1]).toEqual({value: 'import', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.import.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'file', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); - return it("tokenizes '#include_next'", function() { + it("tokenizes '#include_next'", function() { const {tokens} = grammar.tokenizeLine('#include_next "next.h"'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'include_next', scopes: ['source.c', 'meta.preprocessor.include.c', 'keyword.control.directive.include_next.c']}); expect(tokens[3]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.begin.c']}); expect(tokens[4]).toEqual({value: 'next.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c']}); - return expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); + expect(tokens[5]).toEqual({value: '"', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.double.include.c', 'punctuation.definition.string.end.c']}); }); }); @@ -422,18 +422,18 @@ int something(int param) { const {tokens} = grammar.tokenizeLine('#error "C++ compiler required."'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'error', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.error.c']}); - return expect(tokens[4]).toEqual({value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); + expect(tokens[4]).toEqual({value: 'C++ compiler required.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); }); - return it("tokenizes '#warning'", function() { + it("tokenizes '#warning'", function() { const {tokens} = grammar.tokenizeLine('#warning "This is a warning."'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c', 'punctuation.definition.directive.c']}); expect(tokens[1]).toEqual({value: 'warning', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'keyword.control.directive.diagnostic.warning.c']}); - return expect(tokens[4]).toEqual({value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); + expect(tokens[4]).toEqual({value: 'This is a warning.', scopes: ['source.c', 'meta.preprocessor.diagnostic.c', 'string.quoted.double.c']}); }); }); - return describe("conditionals", function() { + describe("conditionals", function() { it("tokenizes if-elif-else preprocessor blocks", function() { const lines = grammar.tokenizeLines(`\ #if defined(CREDIT) @@ -465,7 +465,7 @@ int something(int param) { expect(lines[5][2]).toEqual({value: '(', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.begin.bracket.round.c']}); expect(lines[5][3]).toEqual({value: ')', scopes: ['source.c', 'meta.function.c', 'punctuation.section.parameters.end.bracket.round.c']}); expect(lines[6][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes if-true-else blocks", function() { @@ -504,7 +504,7 @@ int something() { expect(lines[8][1]).toEqual({value: 'else', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); expect(lines[9][0]).toEqual({value: 'int something() {', scopes: ['source.c', 'comment.block.preprocessor.else-branch.c']}); expect(lines[12][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[12][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[12][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes if-false-else blocks", function() { @@ -542,7 +542,7 @@ int something() { expect(lines[0][3]).toEqual({value: '0', scopes: ['source.c', 'meta.preprocessor.c', 'constant.numeric.c']}); expect(lines[1][0]).toEqual({value: ' something();', scopes: ['source.c', 'comment.block.preprocessor.if-branch.c']}); expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes ifdef-elif blocks", function() { @@ -578,7 +578,7 @@ int something() { expect(lines[3][5]).toEqual({value: 'windows.h', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c']}); expect(lines[3][6]).toEqual({value: '>', scopes: ['source.c', 'meta.preprocessor.include.c', 'string.quoted.other.lt-gt.include.c', 'punctuation.definition.string.end.c']}); expect(lines[4][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[4][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[4][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes ifndef blocks", function() { @@ -595,7 +595,7 @@ int something() { expect(lines[1][2]).toEqual({value: 'define', scopes: ['source.c', 'meta.preprocessor.macro.c', 'keyword.control.directive.define.c']}); expect(lines[1][4]).toEqual({value: '_INCL_GUARD', scopes: ['source.c', 'meta.preprocessor.macro.c', 'entity.name.function.preprocessor.c']}); expect(lines[2][0]).toEqual({value: '#', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[2][1]).toEqual({value: 'endif', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("highlights stray elif, else and endif usages as invalid", function() { @@ -610,12 +610,12 @@ int something() { ); expect(lines[2][0]).toEqual({value: '#elif', scopes: ['source.c', 'invalid.illegal.stray-elif.c']}); expect(lines[4][0]).toEqual({value: '#else', scopes: ['source.c', 'invalid.illegal.stray-else.c']}); - return expect(lines[5][0]).toEqual({value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c']}); + expect(lines[5][0]).toEqual({value: '#endif', scopes: ['source.c', 'invalid.illegal.stray-endif.c']}); }); it("highlights errorneous defined usage as invalid", function() { const {tokens} = grammar.tokenizeLine('#if defined == VALUE'); - return expect(tokens[3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c']}); + expect(tokens[3]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'invalid.illegal.macro-name.c']}); }); it("tokenizes multi line conditional queries", function() { @@ -652,14 +652,14 @@ int something() { expect(lines[4][6]).toEqual({value: '*', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.c']}); expect(lines[4][9]).toEqual({value: ')', scopes: ['source.c', 'meta.preprocessor.c', 'punctuation.section.parens.end.bracket.round.c']}); expect(lines[4][11]).toEqual({value: '//', scopes: ['source.c', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); - return expect(lines[4][12]).toEqual({value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp']}); + expect(lines[4][12]).toEqual({value: ' single line comment', scopes: ['source.c', 'comment.line.double-slash.cpp']}); }); - return it("tokenizes ternary operator usage in preprocessor conditionals", function() { + it("tokenizes ternary operator usage in preprocessor conditionals", function() { const {tokens} = grammar.tokenizeLine('#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)'); expect(tokens[9]).toEqual({value: '?', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); expect(tokens[11]).toEqual({value: 'defined', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); - return expect(tokens[17]).toEqual({value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); + expect(tokens[17]).toEqual({value: ':', scopes: ['source.c', 'meta.preprocessor.c', 'keyword.operator.ternary.c']}); }); }); }); @@ -669,7 +669,7 @@ int something() { beforeEach(function() { editor = buildTextEditor(); - return editor.setGrammar(grammar); + editor.setGrammar(grammar); }); const expectPreservedIndentation = function(text) { @@ -678,7 +678,7 @@ int something() { const expectedLines = text.split('\n'); const actualLines = editor.getText().split('\n'); - return Array.from(actualLines).map((actualLine, i) => + Array.from(actualLines).map((actualLine, i) => expect([ actualLine, editor.indentLevelForLine(actualLine) @@ -737,9 +737,9 @@ some_t a[3] = { ` )); - return it("tokenizes binary literal", function() { + it("tokenizes binary literal", function() { const {tokens} = grammar.tokenizeLine('0b101010'); - return expect(tokens[0]).toEqual({value: '0b101010', scopes: ['source.c', 'constant.numeric.c']}); + expect(tokens[0]).toEqual({value: '0b101010', scopes: ['source.c', 'constant.numeric.c']}); }); }); @@ -799,10 +799,10 @@ some_t a[3] = { ` ); expect(lines[1][1]).toEqual({value: '.', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.dot-access.c']}); - return expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); + expect(lines[1][3]).toEqual({value: 'b', scopes: ['source.c', 'meta.block.c', 'variable.other.member.c']}); }); - return it("tokenizes the pointer access operator", function() { + it("tokenizes the pointer access operator", function() { let lines = grammar.tokenizeLines(`\ { a->b; @@ -855,11 +855,11 @@ some_t a[3] = { ` ); expect(lines[1][0]).toEqual({value: ' a', scopes: ['source.c', 'meta.block.c']}); - return expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); + expect(lines[1][1]).toEqual({value: '->', scopes: ['source.c', 'meta.block.c', 'punctuation.separator.pointer-access.c']}); }); }); - return describe("operators", function() { + describe("operators", function() { it("tokenizes the sizeof operator", function() { let {tokens} = grammar.tokenizeLine('sizeof unary_expression'); expect(tokens[0]).toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); @@ -879,7 +879,7 @@ some_t a[3] = { expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); ({tokens} = grammar.tokenizeLine('sizeof_')); - return expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); + expect(tokens[0]).not.toEqual({value: 'sizeof', scopes: ['source.c', 'keyword.operator.sizeof.c']}); }); it("tokenizes the increment operator", function() { @@ -889,7 +889,7 @@ some_t a[3] = { ({tokens} = grammar.tokenizeLine('++i')); expect(tokens[0]).toEqual({value: '++', scopes: ['source.c', 'keyword.operator.increment.c']}); - return expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); }); it("tokenizes the decrement operator", function() { @@ -899,7 +899,7 @@ some_t a[3] = { ({tokens} = grammar.tokenizeLine('--i')); expect(tokens[0]).toEqual({value: '--', scopes: ['source.c', 'keyword.operator.decrement.c']}); - return expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: 'i', scopes: ['source.c']}); }); it("tokenizes logical operators", function() { @@ -956,7 +956,7 @@ some_t a[3] = { expect(tokens[1]).toEqual({value: '?', scopes: ['source.c', 'keyword.operator.ternary.c']}); expect(tokens[2]).toEqual({value: ' b ', scopes: ['source.c']}); expect(tokens[3]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - return expect(tokens[4]).toEqual({value: ' c', scopes: ['source.c']}); + expect(tokens[4]).toEqual({value: ' c', scopes: ['source.c']}); }); it("tokenizes ternary operators with member access", function() { @@ -968,7 +968,7 @@ some_t a[3] = { expect(tokens[4]).toEqual({value: 'c', scopes: ['source.c', 'variable.other.member.c']}); expect(tokens[5]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[6]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - return expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); + expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); }); it("tokenizes ternary operators with pointer dereferencing", function() { @@ -980,7 +980,7 @@ some_t a[3] = { expect(tokens[4]).toEqual({value: 'c', scopes: ['source.c', 'variable.other.member.c']}); expect(tokens[5]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[6]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - return expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); + expect(tokens[7]).toEqual({value: ' d', scopes: ['source.c']}); }); it("tokenizes ternary operators with function invocation", function() { @@ -994,14 +994,14 @@ some_t a[3] = { expect(tokens[6]).toEqual({value: ')', scopes: ['source.c', 'meta.function-call.c', 'punctuation.section.arguments.end.bracket.round.c']}); expect(tokens[7]).toEqual({value: ' ', scopes: ['source.c']}); expect(tokens[8]).toEqual({value: ':', scopes: ['source.c', 'keyword.operator.ternary.c']}); - return expect(tokens[9]).toEqual({value: ' c', scopes: ['source.c']}); + expect(tokens[9]).toEqual({value: ' c', scopes: ['source.c']}); }); describe("bitwise", function() { it("tokenizes bitwise 'not'", function() { const {tokens} = grammar.tokenizeLine('~a'); expect(tokens[0]).toEqual({value: '~', scopes: ['source.c', 'keyword.operator.c']}); - return expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c']}); + expect(tokens[1]).toEqual({value: 'a', scopes: ['source.c']}); }); it("tokenizes shift operators", function() { @@ -1009,10 +1009,10 @@ some_t a[3] = { expect(tokens[0]).toEqual({value: '>>', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); ({tokens} = grammar.tokenizeLine('<<')); - return expect(tokens[0]).toEqual({value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); + expect(tokens[0]).toEqual({value: '<<', scopes: ['source.c', 'keyword.operator.bitwise.shift.c']}); }); - return it("tokenizes them", function() { + it("tokenizes them", function() { const operators = ['|', '^', '&']; return (() => { @@ -1028,12 +1028,12 @@ some_t a[3] = { }); }); - return describe("assignment", function() { + describe("assignment", function() { it("tokenizes the assignment operator", function() { const {tokens} = grammar.tokenizeLine('a = b'); expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.c']}); expect(tokens[1]).toEqual({value: '=', scopes: ['source.c', 'keyword.operator.assignment.c']}); - return expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); + expect(tokens[2]).toEqual({value: ' b', scopes: ['source.c']}); }); it("tokenizes compound assignment operators", function() { @@ -1050,7 +1050,7 @@ some_t a[3] = { })(); }); - return it("tokenizes bitwise compound operators", function() { + it("tokenizes bitwise compound operators", function() { const operators = ['<<=', '>>=', '&=', '^=', '|=']; return (() => { const result = []; @@ -1067,17 +1067,17 @@ some_t a[3] = { }); }); - return describe("C++", function() { + describe("C++", function() { beforeEach(() => grammar = atom.grammars.grammarForScopeName('source.cpp')); it("parses the grammar", function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe('source.cpp'); + expect(grammar.scopeName).toBe('source.cpp'); }); it("tokenizes this with `.this` class", function() { const {tokens} = grammar.tokenizeLine('this.x'); - return expect(tokens[0]).toEqual({value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp']}); + expect(tokens[0]).toEqual({value: 'this', scopes: ['source.cpp', 'variable.language.this.cpp']}); }); it("tokenizes classes", function() { @@ -1088,7 +1088,7 @@ class Thing { ` ); expect(lines[0][0]).toEqual({value: 'class', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'storage.type.cpp']}); - return expect(lines[0][2]).toEqual({value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp']}); + expect(lines[0][2]).toEqual({value: 'Thing', scopes: ['source.cpp', 'meta.class-struct-block.cpp', 'entity.name.type.cpp']}); }); it("tokenizes 'extern C'", function() { @@ -1136,7 +1136,7 @@ extern "C" { expect(lines[4][1]).toEqual({value: 'ifdef', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); expect(lines[5][0]).toEqual({value: '}', scopes: ['source.cpp']}); expect(lines[6][0]).toEqual({value: '#', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c', 'punctuation.definition.directive.c']}); - return expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); + expect(lines[6][1]).toEqual({value: 'endif', scopes: ['source.cpp', 'meta.preprocessor.c', 'keyword.control.directive.conditional.c']}); }); it("tokenizes UTF string escapes", function() { @@ -1155,7 +1155,7 @@ string str = U"\\U01234567\\u0123\\"\\0123\\x123";\ expect(lines[0][9]).toEqual({value: '3', scopes: ['source.cpp', 'string.quoted.double.cpp']}); expect(lines[0][10]).toEqual({value: '\\x123', scopes: ['source.cpp', 'string.quoted.double.cpp', 'constant.character.escape.cpp']}); expect(lines[0][11]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); - return expect(lines[0][12]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + expect(lines[0][12]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("tokenizes % format specifiers", function() { @@ -1172,7 +1172,7 @@ string str = U"\\U01234567\\u0123\\"\\0123\\x123";\ ({tokens} = grammar.tokenizeLine('"%" PRId32')); expect(tokens[0]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.begin.cpp']}); expect(tokens[1]).toEqual({value: '%', scopes: ['source.cpp', 'string.quoted.double.cpp']}); - return expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); + expect(tokens[2]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.cpp', 'punctuation.definition.string.end.cpp']}); }); it("tokenizes raw string literals", function() { @@ -1186,7 +1186,7 @@ string str = R"test( expect(lines[0][3]).toEqual({value: 'R"test(', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.begin.cpp']}); expect(lines[1][0]).toEqual({value: ' this is "a" test \'string\'', scopes: ['source.cpp', 'string.quoted.double.raw.cpp']}); expect(lines[2][0]).toEqual({value: ')test"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); - return expect(lines[2][1]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + expect(lines[2][1]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("errors on long raw string delimiters", function() { @@ -1201,7 +1201,7 @@ string str = R"01234567890123456()01234567890123456";\ expect(lines[0][6]).toEqual({value: ')', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); expect(lines[0][7]).toEqual({value: '01234567890123456', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp', 'invalid.illegal.delimiter-too-long.cpp']}); expect(lines[0][8]).toEqual({value: '"', scopes: ['source.cpp', 'string.quoted.double.raw.cpp', 'punctuation.definition.string.end.cpp']}); - return expect(lines[0][9]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); + expect(lines[0][9]).toEqual({value: ';', scopes: ['source.cpp', 'punctuation.terminator.statement.c']}); }); it("tokenizes destructors", function() { @@ -1217,7 +1217,7 @@ string str = R"01234567890123456()01234567890123456";\ expect(tokens[1]).toEqual({value: '(', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.begin.c']}); expect(tokens[2]).toEqual({value: ')', scopes: ['source.cpp', 'meta.function.destructor.cpp', 'punctuation.definition.parameters.end.c']}); expect(tokens[4]).toEqual({value: '{', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.begin.bracket.curly.c']}); - return expect(tokens[5]).toEqual({value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.cpp', 'meta.block.c', 'punctuation.section.block.end.bracket.curly.c']}); }); describe("digit separators", function() { @@ -1235,17 +1235,17 @@ string str = R"01234567890123456()01234567890123456";\ expect(tokens[0]).toEqual({value: "0'123'456", scopes: ['source.cpp', 'constant.numeric.c']}); ({tokens} = grammar.tokenizeLine("0b1100'0011'1111'0000")); - return expect(tokens[0]).toEqual({value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c']}); + expect(tokens[0]).toEqual({value: "0b1100'0011'1111'0000", scopes: ['source.cpp', 'constant.numeric.c']}); }); - return it("does not tokenize single quotes at the beginning or end of numbers as digit separators", function() { + it("does not tokenize single quotes at the beginning or end of numbers as digit separators", function() { let {tokens} = grammar.tokenizeLine("'1000"); expect(tokens[0]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); expect(tokens[1]).toEqual({value: "1000", scopes: ['source.cpp', 'string.quoted.single.c']}); ({tokens} = grammar.tokenizeLine("1000'")); expect(tokens[0]).toEqual({value: "1000", scopes: ['source.cpp', 'constant.numeric.c']}); - return expect(tokens[1]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); + expect(tokens[1]).toEqual({value: "'", scopes: ['source.cpp', 'string.quoted.single.c', 'punctuation.definition.string.begin.c']}); }); }); @@ -1272,10 +1272,10 @@ comment\ ); expect(lines[1][0]).toEqual({value: '//', scopes: ['source.cpp', 'comment.line.double-slash.cpp', 'punctuation.definition.comment.cpp']}); expect(lines[1][1]).toEqual({value: ' not separated\\ ', scopes: ['source.cpp', 'comment.line.double-slash.cpp']}); - return expect(lines[2][0]).toEqual({value: 'comment', scopes: ['source.cpp']}); + expect(lines[2][0]).toEqual({value: 'comment', scopes: ['source.cpp']}); })); - return describe("operators", () => it("tokenizes ternary operators with namespace resolution", function() { + describe("operators", () => it("tokenizes ternary operators with namespace resolution", function() { const {tokens} = grammar.tokenizeLine('a ? ns::b : ns::c'); expect(tokens[0]).toEqual({value: 'a ', scopes: ['source.cpp']}); expect(tokens[1]).toEqual({value: '?', scopes: ['source.cpp', 'keyword.operator.ternary.c']}); @@ -1285,7 +1285,7 @@ comment\ expect(tokens[5]).toEqual({value: ':', scopes: ['source.cpp', 'keyword.operator.ternary.c']}); expect(tokens[6]).toEqual({value: ' ns', scopes: ['source.cpp']}); expect(tokens[7]).toEqual({value: '::', scopes: ['source.cpp', 'punctuation.separator.namespace.access.cpp']}); - return expect(tokens[8]).toEqual({value: 'c', scopes: ['source.cpp']}); + expect(tokens[8]).toEqual({value: 'c', scopes: ['source.cpp']}); })); }); }); From 096a14517ff62a730be560adce503bce7d626ff5 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sun, 9 Jul 2023 23:23:57 -0700 Subject: [PATCH 15/18] Revert "Revert "`language-c` remove decaf suggestions"" This reverts commit d13256434176b83aecb940f2cb8e67776c2570bd. --- packages/language-c/spec/c-spec.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/language-c/spec/c-spec.js b/packages/language-c/spec/c-spec.js index 4b5f8df793..066edf31d3 100644 --- a/packages/language-c/spec/c-spec.js +++ b/packages/language-c/spec/c-spec.js @@ -1,11 +1,4 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS205: Consider reworking code to avoid use of IIFEs - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + let TextEditor = null; const buildTextEditor = function(params) { if (atom.workspace.buildTextEditor != null) { From 6afa5db9dd84bb2bf659f7475fca0c2a93999e2a Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sun, 9 Jul 2023 23:24:01 -0700 Subject: [PATCH 16/18] Revert "Revert "Decaf `language-css`"" This reverts commit 3156dbfbb4a2bb44acf223f9743fbd2b36d3687a. --- packages/language-css/spec/css-spec.coffee | 3638 -------------------- packages/language-css/spec/css-spec.js | 494 ++- 2 files changed, 244 insertions(+), 3888 deletions(-) delete mode 100644 packages/language-css/spec/css-spec.coffee diff --git a/packages/language-css/spec/css-spec.coffee b/packages/language-css/spec/css-spec.coffee deleted file mode 100644 index 66d14a3e09..0000000000 --- a/packages/language-css/spec/css-spec.coffee +++ /dev/null @@ -1,3638 +0,0 @@ -describe 'CSS grammar', -> - grammar = null - - beforeEach -> - atom.config.set 'core.useTreeSitterParsers', false - - waitsForPromise -> - atom.packages.activatePackage('language-css') - - runs -> - grammar = atom.grammars.grammarForScopeName('source.css') - - it 'parses the grammar', -> - expect(grammar).toBeTruthy() - expect(grammar.scopeName).toBe 'source.css' - - describe 'selectors', -> - it 'tokenizes type selectors', -> - {tokens} = grammar.tokenizeLine 'p {}' - expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - - it 'tokenizes the universal selector', -> - {tokens} = grammar.tokenizeLine '*' - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - - it 'tokenises combinators', -> - {tokens} = grammar.tokenizeLine 'a > b + * ~ :not(.nah)' - expect(tokens[2]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(tokens[6]).toEqual value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(tokens[10]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - - it 'highlights deprecated combinators', -> - {tokens} = grammar.tokenizeLine '.sooo /deep/ >>>_.>>>' - expect(tokens[3]).toEqual value: '/deep/', scopes: ['source.css', 'invalid.deprecated.combinator.css'] - expect(tokens[5]).toEqual value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css'] - - it 'tokenizes complex selectors', -> - {tokens} = grammar.tokenizeLine '[disabled], [disabled] + p' - expect(tokens[0]).toEqual value: '[', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.begin.bracket.square.css"] - expect(tokens[1]).toEqual value: 'disabled', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "entity.other.attribute-name.css"] - expect(tokens[2]).toEqual value: ']', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.end.bracket.square.css"] - expect(tokens[3]).toEqual value: ',', scopes: ["source.css", "meta.selector.css", "punctuation.separator.list.comma.css"] - expect(tokens[5]).toEqual value: '[', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.begin.bracket.square.css"] - expect(tokens[6]).toEqual value: 'disabled', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "entity.other.attribute-name.css"] - expect(tokens[7]).toEqual value: ']', scopes: ["source.css", "meta.selector.css", "meta.attribute-selector.css", "punctuation.definition.entity.end.bracket.square.css"] - expect(tokens[9]).toEqual value: '+', scopes: ["source.css", "meta.selector.css", "keyword.operator.combinator.css"] - expect(tokens[11]).toEqual value: 'p', scopes: ["source.css", "meta.selector.css", "entity.name.tag.css"] - - lines = grammar.tokenizeLines """ - [disabled]:not(:first-child)::before:hover - ~ div.object - + #id.thing:hover > strong ~ p::before, - a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], - *>em.i.ly[data-name|="Life"] { } - """ - expect(lines[0][0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[0][1]).toEqual value: 'disabled', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[0][2]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(lines[0][3]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][4]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[0][5]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[0][6]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][7]).toEqual value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[0][8]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[0][9]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(lines[0][10]).toEqual value: 'before', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[0][11]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][12]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[1][1]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[1][3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[1][4]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[1][5]).toEqual value: 'object', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[2][1]).toEqual value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[2][3]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(lines[2][4]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(lines[2][5]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[2][6]).toEqual value: 'thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[2][7]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[2][8]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[2][10]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[2][12]).toEqual value: 'strong', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[2][14]).toEqual value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[2][16]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[2][17]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(lines[2][18]).toEqual value: 'before', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[2][19]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[3][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'invalid.illegal.colon.css'] - expect(lines[3][3]).toEqual value: 'last-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[3][4]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][5]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][6]).toEqual value: 'Comment', scopes: ['source.css', 'comment.block.css'] - expect(lines[3][7]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[3][8]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(lines[3][9]).toEqual value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[3][11]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[3][13]).toEqual value: 'html', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[3][14]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[3][15]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[3][16]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[3][17]).toEqual value: 'en-AU', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(lines[3][18]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(lines[3][19]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(lines[4][1]).toEqual value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[4][2]).toEqual value: 'em', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][3]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[4][4]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[4][5]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[4][6]).toEqual value: 'ly', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[4][7]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[4][8]).toEqual value: 'data-name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[4][9]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[4][10]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[4][11]).toEqual value: 'Life', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(lines[4][12]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[4][13]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(lines[4][15]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[4][17]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'custom elements (as type selectors)', -> - it 'only tokenizes identifiers beginning with [a-z]', -> - {tokens} = grammar.tokenizeLine 'pearl-1941 1941-pearl -pearl-1941' - expect(tokens[0]).toEqual value: 'pearl-1941', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css'] - - it 'tokenizes custom elements containing non-ASCII letters', -> - {tokens} = grammar.tokenizeLine 'pokémon-ピカチュウ' - expect(tokens[0]).toEqual value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - - it 'does not tokenize identifiers containing [A-Z]', -> - {tokens} = grammar.tokenizeLine 'Basecamp-schedule basecamp-Schedule' - expect(tokens[0]).toEqual value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css'] - - it 'does not tokenize identifiers containing no hyphens', -> - {tokens} = grammar.tokenizeLine 'halo_night' - expect(tokens[0]).toEqual value: 'halo_night', scopes: ['source.css', 'meta.selector.css'] - - it 'does not tokenise identifiers following an @ symbol', -> - {tokens} = grammar.tokenizeLine('@some-weird-new-feature') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - it 'does not tokenise identifiers in unfamiliar functions', -> - {tokens} = grammar.tokenizeLine('some-edgy-new-function()') - expect(tokens[0]).toEqual value: 'some-edgy-new-function(', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[1]).toEqual value: ')', scopes: ['source.css'] - - describe 'attribute selectors', -> - it 'tokenizes attribute selectors without values', -> - {tokens} = grammar.tokenizeLine '[title]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[2]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes attribute selectors with identifier values', -> - {tokens} = grammar.tokenizeLine '[hreflang|=fr]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: 'hreflang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[2]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[3]).toEqual value: 'fr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[4]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes attribute selectors with string values', -> - {tokens} = grammar.tokenizeLine '[href^="http://www.w3.org/"]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: 'href', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[2]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'http://www.w3.org/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes CSS qualified attribute names with wildcard prefix', -> - {tokens} = grammar.tokenizeLine '[*|title]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[3]).toEqual value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[4]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes CSS qualified attribute names with namespace prefix', -> - {tokens} = grammar.tokenizeLine '[marvel|origin=radiation]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: 'marvel', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[3]).toEqual value: 'origin', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[4]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[5]).toEqual value: 'radiation', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenizes CSS qualified attribute names without namespace prefix', -> - {tokens} = grammar.tokenizeLine '[|data-hp="75"]' - expect(tokens[0]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: 'data-hp', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[5]).toEqual value: '75', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises compound ID/attribute selectors', -> - {tokens} = grammar.tokenizeLine('#div[id="0"]{ }') - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[2]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[3]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[8]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - {tokens} = grammar.tokenizeLine('.bar#div[id="0"]') - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'bar', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[2]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[4]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[5]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - - it 'tokenises compound class/attribute selectors', -> - {tokens} = grammar.tokenizeLine('.div[id="0"]{ }') - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[2]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[3]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[8]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - {tokens} = grammar.tokenizeLine('#bar.div[id]') - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'bar', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[2]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[3]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[4]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[5]).toEqual value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'allows whitespace to be inserted between tokens', -> - {tokens} = grammar.tokenizeLine('span[ er|lang |= "%%" ]') - expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[3]).toEqual value: 'er', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[4]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[5]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[7]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[10]).toEqual value: '%%', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[11]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[12]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[13]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises escape sequences inside attribute selectors', -> - {tokens} = grammar.tokenizeLine('a[name\\[0\\]="value"]') - expect(tokens[2]).toEqual value: 'name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[3]).toEqual value: '\\[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] - expect(tokens[4]).toEqual value: '0', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[5]).toEqual value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] - expect(tokens[6]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[10]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises escape sequences inside namespace prefixes', -> - {tokens} = grammar.tokenizeLine('a[name\\ space|Get\\ It\\?="kek"]') - expect(tokens[2]).toEqual value: 'name', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[3]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css', 'constant.character.escape.css'] - expect(tokens[4]).toEqual value: 'space', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[5]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[6]).toEqual value: 'Get', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[7]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] - expect(tokens[8]).toEqual value: 'It', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[9]).toEqual value: '\\?', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css'] - expect(tokens[10]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[14]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises comments inside attribute selectors', -> - {tokens} = grammar.tokenizeLine('span[/*]*/lang]') - expect(tokens[0]).toEqual value: 'span', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(tokens[6]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises quoted strings in attribute selectors', -> - {tokens} = grammar.tokenizeLine('a[href^="#"] a[href^= "#"] a[href^="#" ]') - expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[5]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[12]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[13]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[14]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[15]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[16]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[23]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[24]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(tokens[25]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[26]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[27]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - {tokens} = grammar.tokenizeLine("a[href^='#'] a[href^= '#'] a[href^='#' ]") - expect(tokens[4]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[5]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] - expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[12]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[13]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[14]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[15]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] - expect(tokens[16]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[23]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[24]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] - expect(tokens[25]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[26]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[27]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises unquoted strings in attribute selectors', -> - {tokens} = grammar.tokenizeLine('span[class~=Java]') - expect(tokens[3]).toEqual value: '~=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[4]).toEqual value: 'Java', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[5]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - {tokens} = grammar.tokenizeLine('span[class^= 0xDEADCAFE=|~BEEFBABE ]') - expect(tokens[3]).toEqual value: '^=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[5]).toEqual value: '0xDEADCAFE=|~BEEFBABE', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises escape sequences in unquoted strings', -> - {tokens} = grammar.tokenizeLine('a[name\\[0\\]=a\\BAD\\AF\\]a\\ i] {}') - expect(tokens[6]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[7]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[8]).toEqual value: '\\BAD', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.codepoint.css'] - expect(tokens[9]).toEqual value: '\\AF', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.codepoint.css'] - expect(tokens[10]).toEqual value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css'] - expect(tokens[11]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[12]).toEqual value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css'] - expect(tokens[13]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[14]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[16]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises the ignore-case modifier at the end of a selector', -> - {tokens} = grammar.tokenizeLine('a[attr=val i] a[attr="val" i] a[attr=\'val\'I] a[val^= \'"\'i] a[attr= i] a[attr= i i]') - expect(tokens[6]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[7]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[16]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[17]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[26]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[27]).toEqual value: 'I', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[28]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[34]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[35]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[36]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css'] - expect(tokens[37]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[38]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[39]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[44]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[45]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[46]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[47]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(tokens[52]).toEqual value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(tokens[53]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[54]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css'] - expect(tokens[55]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(tokens[56]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(tokens[57]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - it 'tokenises attribute selectors spanning multiple lines', -> - lines = grammar.tokenizeLines """ - span[ - \\x20{2} - ns|lang/**/ - |= - "pt"] - """ - expect(lines[0][0]).toEqual value: 'span', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[0][1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[1][0]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css'] - expect(lines[2][1]).toEqual value: 'ns', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(lines[2][2]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(lines[2][3]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][5]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[3][1]).toEqual value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[4][0]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[4][1]).toEqual value: 'pt', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(lines[4][2]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[4][3]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - lines = grammar.tokenizeLines """ - span[/*=== - ==|span[/*} - ====*/*|lang/*]=*/~=/*"|"*/"en-AU"/* - | - */ - i] - """ - expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][3]).toEqual value: '===', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[1][0]).toEqual value: '==|span[/*}', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[2][0]).toEqual value: '====', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(lines[2][3]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(lines[2][4]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[2][5]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][6]).toEqual value: ']=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[2][7]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][8]).toEqual value: '~=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[2][9]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][10]).toEqual value: '"|"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[2][11]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][12]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[2][13]).toEqual value: 'en-AU', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(lines[2][14]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[2][15]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][0]).toEqual value: ' |', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css'] - expect(lines[4][0]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[5][0]).toEqual value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css'] - expect(lines[5][1]).toEqual value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - - describe 'class selectors', -> - it 'tokenizes class selectors containing non-ASCII letters', -> - {tokens} = grammar.tokenizeLine '.étendard' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'étendard', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - {tokens} = grammar.tokenizeLine '.スポンサー' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - it 'tokenizes a class selector consisting of two hypens', -> - {tokens} = grammar.tokenizeLine '.--' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - it 'tokenizes class selectors consisting of one (valid) character', -> - {tokens} = grammar.tokenizeLine '._' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - it 'tokenises class selectors starting with an escape sequence', -> - {tokens} = grammar.tokenizeLine '.\\33\\44-model {' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css'] - expect(tokens[2]).toEqual value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css'] - expect(tokens[3]).toEqual value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises class selectors ending with an escape sequence', -> - {tokens} = grammar.tokenizeLine '.la\\{tex\\} {' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css'] - expect(tokens[3]).toEqual value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[4]).toEqual value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css'] - expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks a class invalid if it contains unescaped ASCII punctuation or symbols other than "-" and "_"', -> - {tokens} = grammar.tokenizeLine '.B&W{' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'B&W', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks a class invalid if it starts with ASCII digits ([0-9])', -> - {tokens} = grammar.tokenizeLine '.666{' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks a class invalid if it starts with "-" followed by ASCII digits', -> - {tokens} = grammar.tokenizeLine '.-911-{' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks a class invalid if it consists of only one hyphen', -> - {tokens} = grammar.tokenizeLine '.-{' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - describe 'id selectors', -> - it 'tokenizes id selectors consisting of ASCII letters', -> - {tokens} = grammar.tokenizeLine '#unicorn' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - - it 'tokenizes id selectors containing non-ASCII letters', -> - {tokens} = grammar.tokenizeLine '#洪荒之力' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - - it 'tokenizes id selectors containing [0-9], "-", or "_"', -> - {tokens} = grammar.tokenizeLine '#_zer0-day' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - - it 'tokenizes id selectors beginning with two hyphens', -> - {tokens} = grammar.tokenizeLine '#--d3bug--' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - - it 'marks an id invalid if it contains ASCII punctuation or symbols other than "-" and "_"', -> - {tokens} = grammar.tokenizeLine '#sort!{' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'sort!', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks an id invalid if it starts with ASCII digits ([0-9])', -> - {tokens} = grammar.tokenizeLine '#666{' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks an id invalid if it starts with "-" followed by ASCII digits', -> - {tokens} = grammar.tokenizeLine '#-911-{' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'marks an id invalid if it consists of one hyphen only', -> - {tokens} = grammar.tokenizeLine '#-{' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises ID selectors starting with an escape sequence', -> - {tokens} = grammar.tokenizeLine '#\\33\\44-model {' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css'] - expect(tokens[2]).toEqual value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css'] - expect(tokens[3]).toEqual value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises ID selectors ending with an escape sequence', -> - {tokens} = grammar.tokenizeLine '#la\\{tex\\} {' - expect(tokens[0]).toEqual value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css'] - expect(tokens[3]).toEqual value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(tokens[4]).toEqual value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css'] - expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - describe 'namespace prefixes', -> - it 'tokenises arbitrary namespace prefixes', -> - {tokens} = grammar.tokenizeLine('foo|h1 { }') - expect(tokens[0]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenises anonymous namespace prefixes', -> - {tokens} = grammar.tokenizeLine('*|abbr {}') - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: 'abbr', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('*|* {}') - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('foo|* { }') - expect(tokens[0]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[2]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('|[svg|attr=name]{}') - expect(tokens[0]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[1]).toEqual value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(tokens[2]).toEqual value: 'svg', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css'] - expect(tokens[3]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css'] - expect(tokens[4]).toEqual value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - - it 'tokenises the "no-namespace" prefix', -> - {tokens} = grammar.tokenizeLine('|h1 { }') - expect(tokens[0]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css'] - expect(tokens[1]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "doesn't tokenise prefixes without a selector", -> - {tokens} = grammar.tokenizeLine('*| { }') - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('*|{ }') - expect(tokens[0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(tokens[1]).toEqual value: '|', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'at-rules', -> - describe '@charset', -> - # NB: \A won't match if "tokenizeLine" is used; "tokenizeLines" is used here to circumvent this limitation - it 'tokenises @charset rules at the start of a file', -> - lines = grammar.tokenizeLines '@charset "US-ASCII";' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[0][4]).toEqual value: 'US-ASCII', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] - expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[0][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines('/* Not the first line */\n@charset "UTF-8";') - expect(lines[0][0]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][1]).toEqual value: ' Not the first line ', scopes: ['source.css', 'comment.block.css'] - expect(lines[0][2]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] - expect(lines[1][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - it 'highlights invalid @charset statements', -> - lines = grammar.tokenizeLines " @charset 'US-ASCII';" - expect(lines[0][0]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.leading-whitespace.charset.css'] - expect(lines[0][1]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][2]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][4]).toEqual value: "'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-double-quoted.charset.css'] - expect(lines[0][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset "iso-8859-15";' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.whitespace.charset.css'] - expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[0][4]).toEqual value: 'iso-8859-15', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] - expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[0][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset"US-ASCII";' - expect(lines[0][0]).toEqual value: '@charset"US-ASCII"', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.no-whitespace.charset.css'] - expect(lines[0][1]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset "UTF-8" ;' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[0][4]).toEqual value: 'UTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] - expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unexpected-characters.charset.css'] - expect(lines[0][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset "WTF-8" /* Nope */ ;' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[0][4]).toEqual value: 'WTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css'] - expect(lines[0][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.charset.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[0][6]).toEqual value: ' /* Nope */ ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unexpected-characters.charset.css'] - expect(lines[0][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines '@charset "UTF-8' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'charset', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][3]).toEqual value: '"UTF-8', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.unclosed-string.charset.css'] - - lines = grammar.tokenizeLines "@CHARSET 'US-ASCII';" - expect(lines[0][0]).toEqual value: '@CHARSET', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-lowercase.charset.css'] - expect(lines[0][1]).toEqual value: " 'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css'] - expect(lines[0][2]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css'] - - describe '@import', -> - it 'tokenises @import statements', -> - {tokens} = grammar.tokenizeLine('@import url("file.css");') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import "file.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine("@import 'file.css';") - expect(tokens[3]).toEqual value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css'] - expect(tokens[5]).toEqual value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - - it "doesn't let injected comments impact parameter matching", -> - {tokens} = grammar.tokenizeLine('@import /* url("name"); */ "1.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[4]).toEqual value: ' url("name"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[5]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import/* Comment */"2.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: ' Comment ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'correctly handles word boundaries', -> - {tokens} = grammar.tokenizeLine('@import"file.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[3]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import-file.css;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import-file', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - expect(tokens[2]).toEqual value: '.css', scopes: ['source.css', 'meta.at-rule.header.css'] - expect(tokens[3]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css'] - - it 'matches a URL that starts on the next line', -> - lines = grammar.tokenizeLines '@import\nurl("file.css");' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(lines[0][2]).toEqual value: '', scopes: ['source.css', 'meta.at-rule.import.css'] - expect(lines[1][0]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[1][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][3]).toEqual value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[1][5]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'matches comments inside query lists', -> - {tokens} = grammar.tokenizeLine('@import url("1.css") print /* url(";"); */ all;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[10]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[16]).toEqual value: 'all', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] - expect(tokens[17]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'highlights deprecated media types', -> - {tokens} = grammar.tokenizeLine('@import "astral.css" projection;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'astral.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[7]).toEqual value: 'projection', scopes: ['source.css', 'meta.at-rule.import.css', 'invalid.deprecated.constant.media.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'highlights media features in query lists', -> - {tokens} = grammar.tokenizeLine('@import url(\'landscape.css\') screen and (orientation:landscape);') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '\'', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'landscape.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css'] - expect(tokens[7]).toEqual value: '\'', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[14]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[15]).toEqual value: 'orientation', scopes: ['source.css', 'meta.at-rule.import.css', 'support.type.property-name.media.css'] - expect(tokens[16]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.separator.key-value.css'] - expect(tokens[17]).toEqual value: 'landscape', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.property-value.css'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[19]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - describe '@media', -> - it 'tokenises @media keywords correctly', -> - {tokens} = grammar.tokenizeLine('@media(max-width: 37.5em) { }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[3]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[7]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[9]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@media not print and (max-width: 37.5em){ }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.not.media.css'] - expect(tokens[5]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[7]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[10]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[11]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[13]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[14]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[16]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[18]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'highlights deprecated media types', -> - {tokens} = grammar.tokenizeLine('@media (max-device-width: 2px){ }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'max-device-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'highlights vendored media features', -> - {tokens} = grammar.tokenizeLine('@media (-webkit-foo: bar){ b{ } }') - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '-webkit-foo', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: ' bar', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[8]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@media screen and (-ms-high-contrast:black-on-white){ }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[5]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '-ms-high-contrast', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[9]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[10]).toEqual value: 'black-on-white', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@media (_moz-a:b){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '_moz-a', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'b', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('@media (-hp-foo:bar){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '-hp-foo', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'bar', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('@media (mso-page-size:wide){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'mso-page-size', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'wide', scopes: ['source.css', 'meta.at-rule.media.header.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - - it 'tokenises @media immediately following a closing brace', -> - {tokens} = grammar.tokenizeLine('h1 { }@media only screen { } h2 { }') - expect(tokens[0]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[5]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[6]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[8]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - expect(tokens[16]).toEqual value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[18]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[20]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('h1 { }@media only screen { }h2 { }') - expect(tokens[0]).toEqual value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[4]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[5]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[6]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[8]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(tokens[10]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - expect(tokens[15]).toEqual value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[17]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[19]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenises level 4 media-query syntax', -> - lines = grammar.tokenizeLines """ - @media (min-width >= 0px) - and (max-width <= 400) - and (min-height > 400) - and (max-height < 200) - """ - expect(lines[0][6]).toEqual value: '>=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] - expect(lines[1][6]).toEqual value: '<=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] - expect(lines[2][6]).toEqual value: '>', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] - expect(lines[3][6]).toEqual value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css'] - - it 'tokenises comments between media types', -> - {tokens} = grammar.tokenizeLine('@media/* */only/* */screen/* */and (min-width:1100px){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[9]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[10]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[12]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[13]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[15]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[16]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[17]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[18]).toEqual value: '1100', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[19]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[20]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[21]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[22]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'tokenises comments between media features', -> - {tokens} = grammar.tokenizeLine('@media/*=*/(max-width:/**/37.5em)/*=*/and/*=*/(/*=*/min-height/*:*/:/*=*/1.2em/*;*/){}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[10]).toEqual value: '37.5', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[11]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[13]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[14]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[15]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[16]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(tokens[17]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[18]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[19]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[20]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[21]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[22]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[23]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[24]).toEqual value: 'min-height', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[25]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[26]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[27]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[28]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[29]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[30]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[31]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[32]).toEqual value: '1.2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[33]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[34]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[35]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[36]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[37]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(tokens[38]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[39]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'matches media queries across lines', -> - lines = grammar.tokenizeLines """ - @media only screen and (min-width : /* 40 */ - 320px), - not print and (max-width: 480px) /* kek */ and (-webkit-min-device-pixel-ratio /*:*/ : 2), - only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-ratio: 2) { } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(lines[0][3]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(lines[0][5]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(lines[0][7]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(lines[0][9]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[0][10]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(lines[0][12]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[0][14]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][15]).toEqual value: ' 40 ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(lines[0][16]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][1]).toEqual value: '320', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[1][2]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[1][3]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[1][4]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][1]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.not.media.css'] - expect(lines[2][3]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(lines[2][5]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(lines[2][7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[2][8]).toEqual value: 'max-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(lines[2][9]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[2][11]).toEqual value: '480', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[2][12]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[2][13]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[2][15]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][16]).toEqual value: ' kek ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(lines[2][17]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][19]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(lines[2][21]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[2][22]).toEqual value: '-webkit-min-device-pixel-ratio', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(lines[2][24]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][25]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(lines[2][26]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][28]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[2][30]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[2][31]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[2][32]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][0]).toEqual value: 'only', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.only.media.css'] - expect(lines[3][2]).toEqual value: 'speech', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(lines[3][4]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.logical.and.media.css'] - expect(lines[3][6]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[3][7]).toEqual value: 'min-width', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(lines[3][8]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[3][10]).toEqual value: '10', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[3][11]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[3][12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[3][13]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][15]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][16]).toEqual value: ' wat ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(lines[3][17]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[3][19]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(lines[3][20]).toEqual value: '-webkit-min-device-pixel-ratio', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css'] - expect(lines[3][21]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(lines[3][23]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(lines[3][24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - expect(lines[3][26]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(lines[3][28]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'highlights invalid commas', -> - {tokens} = grammar.tokenizeLine('@media , {}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@media , ,screen {}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: ', ,', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css'] - expect(tokens[4]).toEqual value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css'] - expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css'] - - it 'allows spaces inside ratio values', -> - {tokens} = grammar.tokenizeLine('@media (min-aspect-ratio: 3 / 4) and (max-aspect-ratio: 20 / 17) {}') - expect(tokens[7]).toEqual value: '3', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] - expect(tokens[9]).toEqual value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css'] - expect(tokens[10]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] - expect(tokens[11]).toEqual value: '4', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] - expect(tokens[20]).toEqual value: '20', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] - expect(tokens[21]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] - expect(tokens[22]).toEqual value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css'] - expect(tokens[23]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css'] - expect(tokens[24]).toEqual value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css'] - - describe '@keyframes', -> - it 'tokenises keyframe lists correctly', -> - lines = grammar.tokenizeLines """ - @keyframes important1 { - from { margin-top: 50px; - margin-bottom: 100px } - 50% { margin-top: 150px !important; } /* Ignored */ - to { margin-top: 100px; } - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(lines[0][3]).toEqual value: 'important1', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(lines[0][4]).toEqual value: ' ', scopes: ['source.css'] - expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(lines[1][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[1][8]).toEqual value: '50', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[1][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[2][1]).toEqual value: 'margin-bottom', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[2][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[3][1]).toEqual value: '50%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] - expect(lines[3][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[3][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[3][8]).toEqual value: '150', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[3][11]).toEqual value: '!important', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'keyword.other.important.css'] - expect(lines[3][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[3][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[3][16]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][17]).toEqual value: ' Ignored ', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css'] - expect(lines[3][18]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[4][1]).toEqual value: 'to', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(lines[4][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[4][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[4][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[4][8]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[4][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[5][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] - - it 'matches injected comments', -> - lines = grammar.tokenizeLines """ - @keyframes/*{*/___IDENT__/*} - { Nah { margin-top: 2em; } - */{ from - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] - expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[0][5]).toEqual value: '___IDENT__', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] - expect(lines[1][0]).toEqual value: ' { Nah { margin-top: 2em; }', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css'] - expect(lines[2][0]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][1]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] - expect(lines[2][3]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - - it 'matches offset keywords case-insensitively', -> - {tokens} = grammar.tokenizeLine('@keyframes Give-them-both { fROm { } To {} }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(tokens[3]).toEqual value: 'Give-them-both', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] - expect(tokens[7]).toEqual value: 'fROm', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(tokens[9]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[11]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[13]).toEqual value: 'To', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(tokens[15]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[16]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[18]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] - - it 'matches percentile offsets', -> - {tokens} = grammar.tokenizeLine('@keyframes identifier { -50.2% } @keyframes ident2 { .25%}') - expect(tokens[7]).toEqual value: '-50.2%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] - expect(tokens[18]).toEqual value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] - - it 'highlights escape sequences inside identifiers', -> - {tokens} = grammar.tokenizeLine '@keyframes A\\1F602Z' - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(tokens[3]).toEqual value: 'A', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(tokens[4]).toEqual value: '\\1F602', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[5]).toEqual value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - - describe '@supports', -> - it 'tokenises feature queries', -> - {tokens} = grammar.tokenizeLine('@supports (font-size: 1em) { }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.supports.header.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'font-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[7]).toEqual value: '1', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[10]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[11]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(tokens[13]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - it 'matches logical operators', -> - lines = grammar.tokenizeLines """ - @supports not (font-size: 1em){ } - @supports (font-size: 1em) and (font-size: 1em){ } - @supports (font-size: 1em) or (font-size: 1em){ } - """ - expect(lines[0][3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] - expect(lines[1][11]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css'] - expect(lines[2][11]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - - it 'matches custom variables in feature queries', -> - {tokens} = grammar.tokenizeLine('@supports (--foo: green){}') - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '--foo', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'variable.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[7]).toEqual value: 'green', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - - it "doesn't mistake brackets in string literals for feature queries", -> - lines = grammar.tokenizeLines """ - @supports not ((tab-size:4) or (-moz-tab-size:4)){ - body::before{content: "Come on, Microsoft (Get it together already)…"; } - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(lines[0][3]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] - expect(lines[0][7]).toEqual value: 'tab-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[0][12]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'keyword.operator.logical.feature.or.css'] - expect(lines[0][15]).toEqual value: '-moz-tab-size', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - expect(lines[0][20]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[1][2]).toEqual value: '::', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(lines[1][3]).toEqual value: 'before', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[1][4]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][5]).toEqual value: 'content', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[1][8]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][9]).toEqual value: 'Come on, Microsoft (Get it together already)…', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[1][10]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[1][11]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[1][13]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[2][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - it 'tokenises multiple feature queries', -> - {tokens} = grammar.tokenizeLine('@supports (display:table-cell) or ((display:list-item) and (display:run-in)){') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'table-cell', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[9]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - expect(tokens[11]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[12]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[13]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[14]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[15]).toEqual value: 'list-item', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[16]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[18]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'keyword.operator.logical.feature.and.css'] - expect(tokens[20]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(tokens[21]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[22]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(tokens[23]).toEqual value: 'run-in', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[25]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(tokens[26]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - - it 'embeds rulesets and other at-rules', -> - lines = grammar.tokenizeLines """ - @supports (animation-name: test) { - #node { - animation-name: test; - } - body > header[data-name="attr"] ~ *:not(:first-child){ - content: "😂👌" - } - @keyframes important1 { - from { - margin-top: 50px; - margin-bottom: 100px - } - 50% { margin-top: 150px !important; } /* Ignored */ - to { margin-top: 100px; } - } - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(lines[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[0][4]).toEqual value: 'animation-name', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[0][7]).toEqual value: 'test', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css'] - expect(lines[0][8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[0][10]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: '#', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css'] - expect(lines[1][2]).toEqual value: 'node', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.id.css'] - expect(lines[1][4]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[2][1]).toEqual value: 'animation-name', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: 'test', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(lines[2][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[3][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[4][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][3]).toEqual value: '>', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[4][5]).toEqual value: 'header', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][6]).toEqual value: '[', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css'] - expect(lines[4][7]).toEqual value: 'data-name', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css'] - expect(lines[4][8]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css'] - expect(lines[4][9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[4][10]).toEqual value: 'attr', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css'] - expect(lines[4][11]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[4][12]).toEqual value: ']', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css'] - expect(lines[4][14]).toEqual value: '~', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'keyword.operator.combinator.css'] - expect(lines[4][16]).toEqual value: '*', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(lines[4][17]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[4][18]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[4][19]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][20]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[4][21]).toEqual value: 'first-child', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[4][22]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][23]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[5][1]).toEqual value: 'content', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[5][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[5][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[5][5]).toEqual value: '😂👌', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[5][6]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[6][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[7][1]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css'] - expect(lines[7][2]).toEqual value: 'keyframes', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css'] - expect(lines[7][4]).toEqual value: 'important1', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css'] - expect(lines[7][6]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css'] - expect(lines[8][1]).toEqual value: 'from', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(lines[8][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[9][1]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[9][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[9][4]).toEqual value: '50', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[9][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[9][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[10][1]).toEqual value: 'margin-bottom', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[10][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[10][4]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[10][5]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[11][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[12][1]).toEqual value: '50%', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css'] - expect(lines[12][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[12][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[12][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[12][8]).toEqual value: '150', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[12][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[12][11]).toEqual value: '!important', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'keyword.other.important.css'] - expect(lines[12][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[12][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[12][16]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[12][17]).toEqual value: ' Ignored ', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css'] - expect(lines[12][18]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[13][1]).toEqual value: 'to', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css'] - expect(lines[13][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[13][5]).toEqual value: 'margin-top', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[13][6]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[13][8]).toEqual value: '100', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[13][9]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[13][10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[13][12]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[14][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css'] - expect(lines[15][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - it 'matches injected comments', -> - # NB: This particular example actually isn't valid @supports - # syntax; it's just for stress-testing boundary-matching. - lines = grammar.tokenizeLines """ - @supports/*===*/not/*==****************| - ==*/(display:table-cell)/*============*/ and (display: list-item)/*}*/{} - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][3]).toEqual value: '===', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[0][5]).toEqual value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css'] - expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][7]).toEqual value: '==****************|', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[1][3]).toEqual value: 'display', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][4]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[1][5]).toEqual value: 'table-cell', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[1][7]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][8]).toEqual value: '============', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[1][9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][11]).toEqual value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css'] - expect(lines[1][13]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[1][19]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][20]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css'] - expect(lines[1][21]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][22]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(lines[1][23]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - it 'matches feature queries across multiple lines', -> - lines = grammar.tokenizeLines """ - @supports - (box-shadow: 0 0 2px rgba(0,0,0,.5) inset) or - (-moz-box-shadow: 0 0 2px black inset) or - (-webkit-box-shadow: 0 0 2px black inset) or - (-o-box-shadow: 0 0 2px black inset) - { .noticebox { } } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'supports', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.control.at-rule.supports.css'] - expect(lines[1][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[1][2]).toEqual value: 'box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[1][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[1][12]).toEqual value: 'rgba', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[1][13]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][14]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][15]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][16]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][17]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][18]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][19]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][20]).toEqual value: '.5', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][21]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][23]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][24]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[1][26]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - expect(lines[2][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[2][2]).toEqual value: '-moz-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - expect(lines[2][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[2][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[2][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[2][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[2][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[2][17]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - expect(lines[3][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[3][2]).toEqual value: '-webkit-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - expect(lines[3][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[3][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[3][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[3][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[3][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[3][17]).toEqual value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css'] - expect(lines[4][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.begin.bracket.round.css'] - expect(lines[4][2]).toEqual value: '-o-box-shadow', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - expect(lines[4][3]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css'] - expect(lines[4][5]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][7]).toEqual value: '0', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][10]).toEqual value: 'px', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[4][12]).toEqual value: 'black', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[4][14]).toEqual value: 'inset', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[4][15]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css'] - expect(lines[5][0]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css'] - expect(lines[5][2]).toEqual value: '.', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[5][3]).toEqual value: 'noticebox', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(lines[5][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[5][7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[5][9]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css'] - - describe '@namespace', -> - it 'tokenises @namespace statements correctly', -> - {tokens} = grammar.tokenizeLine('@namespace "XML";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@namespace prefix "XML" ;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[3]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@namespace url("http://a.bc/");') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.namespace.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - it "doesn't confuse a prefix of 'url' as a function", -> - {tokens} = grammar.tokenizeLine('@namespace url url("http://a.bc/");') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[5]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[11]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - it 'permits injected comments between tokens', -> - {tokens} = grammar.tokenizeLine('@namespace/*=*/pre/*=*/"url"/*=*/;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[7]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] - expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[10]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(tokens[11]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - it 'allows no spaces between "@namespace" and quoted URLs', -> - {tokens} = grammar.tokenizeLine('@namespace"XML";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(tokens[2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[3]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(tokens[4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - it 'tokenises escape sequences in prefixes', -> - {tokens} = grammar.tokenizeLine('@namespace pre\\ fix "http://url/";') - expect(tokens[3]).toEqual value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[4]).toEqual value: '\\ ', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css', 'constant.character.escape.css'] - expect(tokens[5]).toEqual value: 'fix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - - it 'allows arguments to span multiple lines', -> - lines = grammar.tokenizeLines """ - @namespace - prefix"XML"; - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(lines[1][0]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(lines[1][1]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][2]).toEqual value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css'] - expect(lines[1][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[1][4]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - lines = grammar.tokenizeLines """ - @namespace - - prefix - - url("http://a.bc/"); - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'namespace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(lines[2][1]).toEqual value: 'prefix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css'] - expect(lines[4][0]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[4][1]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][2]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[4][3]).toEqual value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(lines[4][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[4][5]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][6]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css'] - - describe 'font-feature declarations', -> - it 'tokenises font-feature blocks', -> - {tokens} = grammar.tokenizeLine('@font-feature-values Font name 2 { }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css', 'meta.at-rule.font-features.css'] - expect(tokens[3]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'allows font-feature names to start on a different line', -> - lines = grammar.tokenizeLines """ - @font-feature-values - Font name 2 - { - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] - expect(lines[1][0]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(lines[2][0]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'matches injected comments', -> - {tokens} = grammar.tokenizeLine('@font-feature-values/*{*/Font/*}*/name/*{*/2{') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'Font', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] - expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[9]).toEqual value: 'name', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(tokens[10]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[11]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css'] - expect(tokens[12]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[13]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(tokens[14]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises at-rules for feature names', -> - lines = grammar.tokenizeLines """ - @swash{ swashy: 2; } - @ornaments{ ident: 2; } - @annotation{ ident: 1; } - @stylistic{ stylish: 2; } - @styleset{ sets: 2 3 4; } - @character-variant{ charvar: 2 } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] - expect(lines[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[0][4]).toEqual value: 'swashy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[0][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[0][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[0][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css', 'punctuation.definition.keyword.css'] - expect(lines[1][1]).toEqual value: 'ornaments', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css'] - expect(lines[1][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][4]).toEqual value: 'ident', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[1][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[1][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[1][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[2][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css', 'punctuation.definition.keyword.css'] - expect(lines[2][1]).toEqual value: 'annotation', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css'] - expect(lines[2][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[2][4]).toEqual value: 'ident', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[2][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[2][7]).toEqual value: '1', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[2][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.annotation.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[3][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css', 'punctuation.definition.keyword.css'] - expect(lines[3][1]).toEqual value: 'stylistic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css'] - expect(lines[3][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[3][4]).toEqual value: 'stylish', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[3][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[3][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][8]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[3][10]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[4][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css', 'punctuation.definition.keyword.css'] - expect(lines[4][1]).toEqual value: 'styleset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css'] - expect(lines[4][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[4][4]).toEqual value: 'sets', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[4][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[4][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: '3', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][11]).toEqual value: '4', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[4][14]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.styleset.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[5][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css', 'punctuation.definition.keyword.css'] - expect(lines[5][1]).toEqual value: 'character-variant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css'] - expect(lines[5][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[5][4]).toEqual value: 'charvar', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[5][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[5][7]).toEqual value: '2', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[5][9]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'matches feature-name rules case-insensitively', -> - lines = grammar.tokenizeLines """ - @sWASH{ swashy: 2; } - @ornaMENts{ ident: 2; } - @anNOTatION{ ident: 1; } - @styLISTic{ stylish: 2; } - @STYLEset{ sets: 2 3 4; } - @CHARacter-VARiant{ charvar: 2 } - """ - expect(lines[0][1]).toEqual value: 'sWASH', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] - expect(lines[1][1]).toEqual value: 'ornaMENts', scopes: ['source.css', 'meta.at-rule.ornaments.css', 'keyword.control.at-rule.ornaments.css'] - expect(lines[2][1]).toEqual value: 'anNOTatION', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css'] - expect(lines[3][1]).toEqual value: 'styLISTic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css'] - expect(lines[4][1]).toEqual value: 'STYLEset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css'] - expect(lines[5][1]).toEqual value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css'] - - it 'matches comments inside feature-name rules', -> - lines = grammar.tokenizeLines """ - @font-feature-values Font name 2 { - @swash{/* - ========*/swashy:/**/2;/**/} - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css'] - expect(lines[0][3]).toEqual value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css'] - expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][0]).toEqual value: '@', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] - expect(lines[1][1]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] - expect(lines[1][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][3]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][0]).toEqual value: '========', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css'] - expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][2]).toEqual value: 'swashy', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(lines[2][3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][5]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][6]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][7]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.terminator.rule.css'] - expect(lines[2][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[3][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'highlights escape sequences inside feature-names', -> - {tokens} = grammar.tokenizeLine('@swash{ s\\000077a\\73hy: 1; }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css'] - expect(tokens[4]).toEqual value: 's', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(tokens[5]).toEqual value: '\\000077', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css'] - expect(tokens[6]).toEqual value: 'a', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - expect(tokens[7]).toEqual value: '\\73', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css'] - expect(tokens[8]).toEqual value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css'] - - describe '@page', -> - it 'tokenises @page blocks correctly', -> - {tokens} = grammar.tokenizeLine('@page :first { }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[4]).toEqual value: 'first', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[5]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[6]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[8]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@page:right{}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] - expect(tokens[2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[3]).toEqual value: 'right', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('@page{}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe '@counter-style', -> - it 'tokenises them and their contents correctly', -> - lines = grammar.tokenizeLines """ - @counter-style winners-list { - system: fixed; - symbols: url(gold-medal.svg) url(silver-medal.svg) url(bronze-medal.svg); - suffix: " "; - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] - expect(lines[0][3]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: 'system', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] - expect(lines[1][4]).toEqual value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][5]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] - expect(lines[2][1]).toEqual value: 'symbols', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][6]).toEqual value: 'gold-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] - expect(lines[2][7]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][9]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[2][10]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][11]).toEqual value: 'silver-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] - expect(lines[2][12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][14]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[2][15]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][16]).toEqual value: 'bronze-medal.svg', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'variable.parameter.url.css'] - expect(lines[2][17]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][18]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] - expect(lines[3][1]).toEqual value: 'suffix', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] - expect(lines[3][4]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[3][6]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[3][7]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] - expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'matches injected comments', -> - {tokens} = grammar.tokenizeLine('@counter-style/*{*/winners-list/*}*/{ system: fixed; }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - expect(tokens[6]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css'] - expect(tokens[8]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[9]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[11]).toEqual value: 'system', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[12]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css'] - expect(tokens[14]).toEqual value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css'] - expect(tokens[17]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "allows the counter-style's name to start on a different line", -> - lines = grammar.tokenizeLines """ - @counter-style - winners-list - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] - expect(lines[1][0]).toEqual value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - - it "highlights escape sequences inside the style's name", -> - {tokens} = grammar.tokenizeLine '@counter-style A\\01F602z' - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css'] - expect(tokens[3]).toEqual value: 'A', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - expect(tokens[4]).toEqual value: '\\01F602', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css', 'constant.character.escape.codepoint.css'] - expect(tokens[5]).toEqual value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css'] - - describe '@document', -> - it 'correctly tokenises @document rules', -> - lines = grammar.tokenizeLines """ - @document url(http://www.w3.org/), - url-prefix(http://www.w3.org/Style/), /* Comment */ - domain(/**/mozilla.org), - regexp("https:.*") { - body{ color: #f00; } - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: 'document', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css'] - expect(lines[0][3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[0][4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[0][5]).toEqual value: 'http://www.w3.org/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'variable.parameter.url.css'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[0][7]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][1]).toEqual value: 'url-prefix', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] - expect(lines[1][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][3]).toEqual value: 'http://www.w3.org/Style/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'variable.parameter.document-rule.css'] - expect(lines[1][4]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][5]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][7]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][8]).toEqual value: ' Comment ', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css'] - expect(lines[1][9]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][1]).toEqual value: 'domain', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] - expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][5]).toEqual value: 'mozilla.org', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'variable.parameter.document-rule.css'] - expect(lines[2][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][7]).toEqual value: ',', scopes: ['source.css', 'meta.at-rule.document.header.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][1]).toEqual value: 'regexp', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'support.function.document-rule.css'] - expect(lines[3][2]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][3]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[3][4]).toEqual value: 'https:.*', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css'] - expect(lines[3][5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[3][6]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.document.header.css', 'meta.function.document-rule.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][8]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.begin.bracket.curly.css'] - expect(lines[4][1]).toEqual value: 'body', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][2]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[4][4]).toEqual value: 'color', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[4][5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[4][7]).toEqual value: '#', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(lines[4][8]).toEqual value: 'f00', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] - expect(lines[4][9]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][11]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(lines[5][1]).toEqual value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css'] - - describe '@viewport', -> - it 'tokenises @viewport blocks correctly', -> - {tokens} = grammar.tokenizeLine('@viewport { min-width: 640px; max-width: 800px; }') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'viewport', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[3]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[5]).toEqual value: 'min-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[6]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[8]).toEqual value: '640', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[12]).toEqual value: 'max-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[13]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[15]).toEqual value: '800', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[16]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[17]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[19]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenises them across lines', -> - lines = grammar.tokenizeLines """ - @-O-VIEWPORT - { - zoom: 0.75; - min-zoom: 0.5; - max-zoom: 0.9; - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: '-O-VIEWPORT', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] - expect(lines[1][0]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[2][1]).toEqual value: 'zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[2][4]).toEqual value: '0.75', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[3][1]).toEqual value: 'min-zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[3][4]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][1]).toEqual value: 'max-zoom', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[4][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[4][4]).toEqual value: '0.9', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[5][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenises injected comments', -> - lines = grammar.tokenizeLines """ - @-ms-viewport/*{*/{/* - ==*/orientation: landscape; - } - """ - expect(lines[0][0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css', 'punctuation.definition.keyword.css'] - expect(lines[0][1]).toEqual value: '-ms-viewport', scopes: ['source.css', 'meta.at-rule.viewport.css', 'keyword.control.at-rule.viewport.css'] - expect(lines[0][2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][3]).toEqual value: '{', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css'] - expect(lines[0][4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.viewport.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[0][5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[0][6]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css'] - expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][2]).toEqual value: 'orientation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[1][5]).toEqual value: 'landscape', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][6]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[2][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'unknown at-rules', -> - it 'correctly parses single-line unknown at-rules closing with semicolons', -> - lines = grammar.tokenizeLines """ - @foo; - @foo ; - @foo a; - @foo (); - @foo (a); - """ - expect(lines[0][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - expect(lines[1][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - expect(lines[2][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - expect(lines[2][2]).toEqual value: ' a', scopes: ['source.css', 'meta.at-rule.header.css'] - - expect(lines[3][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - expect(lines[3][2]).toEqual value: ' ()', scopes: ['source.css', 'meta.at-rule.header.css'] - - expect(lines[4][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - expect(lines[4][2]).toEqual value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css'] - - it 'correctly parses single-line unknown at-rules closing with ;', -> - lines = grammar.tokenizeLines """ - @foo bar; - .foo - """ - expect(lines[0][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css'] - - expect(lines[1][0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(lines[1][1]).toEqual value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - describe 'capitalisation', -> - it 'ignores case in at-rules', -> - lines = grammar.tokenizeLines """ - @IMPoRT url("file.css"); - @MEdIA (MAX-WIDTH: 2px){ } - @pAgE :fIRST { } - @NAMEspace "A"; - @foNT-FacE {} - """ - expect(lines[0][1]).toEqual value: 'IMPoRT', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(lines[1][1]).toEqual value: 'MEdIA', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(lines[1][4]).toEqual value: 'MAX-WIDTH', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(lines[2][1]).toEqual value: 'pAgE', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css'] - expect(lines[2][4]).toEqual value: 'fIRST', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[3][1]).toEqual value: 'NAMEspace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css'] - expect(lines[4][1]).toEqual value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css'] - - it 'ignores case in property names', -> - lines = grammar.tokenizeLines """ - a{ COLOR: #fff; } - a{ gRId-tEMPLaTe: none; } - a{ bACkgrOUND-iMAGE: none; } - a{ -MOZ-IMAGE: none; } - """ - expect(lines[0][3]).toEqual value: 'COLOR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][3]).toEqual value: 'gRId-tEMPLaTe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][3]).toEqual value: 'bACkgrOUND-iMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][3]).toEqual value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css'] - - it 'ignores case in property keywords', -> - lines = grammar.tokenizeLines """ - a{ color: INItIaL; } - a{ color: trAnsPAREnT; } - a{ color: rED; } - a{ color: unSET; } - a{ color: NONe; } - a{ style: lOWER-lATIN; } - a{ color: -WebkIT-foo; } - a{ font: HelVETica; } - """ - expect(lines[0][6]).toEqual value: 'INItIaL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[1][6]).toEqual value: 'trAnsPAREnT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[2][6]).toEqual value: 'rED', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[3][6]).toEqual value: 'unSET', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[4][6]).toEqual value: 'NONe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(lines[5][6]).toEqual value: 'lOWER-lATIN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css'] - expect(lines[6][6]).toEqual value: '-WebkIT-foo', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] - expect(lines[7][6]).toEqual value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] - - it 'ignores case in selectors', -> - lines = grammar.tokenizeLines """ - DIV:HOVER { } - #id::BefORE { } - #id::aFTEr { } - TABle:nTH-cHILD(2N+1) {} - htML:NOT(.htiml) {} - I::BACKDROP - I::-mOZ-thing {} - """ - expect(lines[0][0]).toEqual value: 'DIV', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[0][2]).toEqual value: 'HOVER', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[1][3]).toEqual value: 'BefORE', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[2][3]).toEqual value: 'aFTEr', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[3][0]).toEqual value: 'TABle', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[3][2]).toEqual value: 'nTH-cHILD', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[3][4]).toEqual value: '2N+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(lines[4][0]).toEqual value: 'htML', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[4][2]).toEqual value: 'NOT', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[5][0]).toEqual value: 'I', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[5][2]).toEqual value: 'BACKDROP', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - expect(lines[6][2]).toEqual value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - it 'ignores case in function names', -> - lines = grammar.tokenizeLines """ - a{ color: RGBa(); } - a{ color: hslA(); } - a{ color: URL(); } - a{ content: ATTr(); } - a{ content: CoUNTer(); } - a{ content: cuBIC-beZIER()} - a{ content: sTePs()} - a{ content: cALc(2 + 2)} - """ - expect(lines[0][6]).toEqual value: 'RGBa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[1][6]).toEqual value: 'hslA', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[2][6]).toEqual value: 'URL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.url.css', 'support.function.url.css'] - expect(lines[3][6]).toEqual value: 'ATTr', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[4][6]).toEqual value: 'CoUNTer', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[5][6]).toEqual value: 'cuBIC-beZIER', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] - expect(lines[6][6]).toEqual value: 'sTePs', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] - expect(lines[7][6]).toEqual value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] - - it 'ignores case in unit names', -> - lines = grammar.tokenizeLines """ - a{width: 20EM; } - a{width: 20ReM; } - a{width: 8tURN; } - a{width: 20S; } - a{width: 20CM} - a{width: 2gRAd} - """ - expect(lines[0][5]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[0][6]).toEqual value: 'EM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[1][6]).toEqual value: 'ReM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.rem.css'] - expect(lines[2][2]).toEqual value: 'width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[2][6]).toEqual value: 'tURN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.turn.css'] - expect(lines[3][6]).toEqual value: 'S', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.s.css'] - expect(lines[4][5]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][6]).toEqual value: 'CM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css'] - expect(lines[5][6]).toEqual value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css'] - - describe 'pseudo-classes', -> - it 'tokenizes regular pseudo-classes', -> - {tokens} = grammar.tokenizeLine 'p:first-child' - expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - - it "doesn't tokenise pseudo-classes if followed by a semicolon or closed bracket", -> - {tokens} = grammar.tokenizeLine('p{ left:left }') - expect(tokens[0]).toEqual value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[5]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe ':dir()', -> - it 'tokenises :dir() and its keywords', -> - lines = grammar.tokenizeLines """ - a:dir(ltr ){ } - *:dir( rtl){ } - """ - expect(lines[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][2]).toEqual value: 'dir', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[0][4]).toEqual value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] - expect(lines[0][5]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] - expect(lines[0][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][0]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css'] - expect(lines[1][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[1][2]).toEqual value: 'dir', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[1][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][4]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] - expect(lines[1][5]).toEqual value: 'rtl', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] - expect(lines[1][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'allows :dir() to include comments and newlines', -> - lines = grammar.tokenizeLines """ - :DIR(/** - ==*/ltr/* - */) - """ - expect(lines[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(lines[0][1]).toEqual value: 'DIR', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(lines[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[0][3]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[0][4]).toEqual value: '*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(lines[1][0]).toEqual value: '==', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(lines[1][1]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][2]).toEqual value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css'] - expect(lines[1][3]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][0]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][1]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - describe ':lang()', -> - it 'tokenizes :lang()', -> - {tokens} = grammar.tokenizeLine ':lang(zh-Hans-CN,es-419)' - expect(tokens[0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'lang', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[3]).toEqual value: 'zh-Hans-CN', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css'] - expect(tokens[4]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(tokens[5]).toEqual value: 'es-419', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'does not tokenize unquoted language ranges containing asterisks', -> - {tokens} = grammar.tokenizeLine ':lang(zh-*-CN)' - expect(tokens[3]).toEqual value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css'] - - it 'tokenizes language ranges containing asterisks quoted as strings', -> - {tokens} = grammar.tokenizeLine ':lang("zh-*-CN",\'*-ab-\')' - expect(tokens[3]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[4]).toEqual value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'support.constant.language-range.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[6]).toEqual value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css'] - expect(tokens[7]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '*-ab-', scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'support.constant.language-range.css'] - expect(tokens[9]).toEqual value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - - describe ':not()', -> - it 'tokenises other selectors inside :not()', -> - {tokens} = grammar.tokenizeLine('*:not(.class-name):not(div) {}') - expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[5]).toEqual value: 'class-name', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[8]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[10]).toEqual value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'tokenises injected comments', -> - {tokens} = grammar.tokenizeLine('*:not(/*(*/.class-name/*)*/):not(/*b*/) {}') - expect(tokens[2]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(tokens[6]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[7]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[8]).toEqual value: 'class-name', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[13]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[14]).toEqual value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[15]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[16]).toEqual value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[17]).toEqual value: 'b', scopes: ['source.css', 'meta.selector.css', 'comment.block.css'] - expect(tokens[18]).toEqual value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[19]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - - describe ':nth-*()', -> - it 'tokenizes :nth-child()', -> - tokens = grammar.tokenizeLines ''' - :nth-child(2n+1) - :nth-child(2n -1) - :nth-child(-2n+ 1) - :nth-child(-2n - 1) - :nth-child(odd) - :nth-child(even) - :nth-child( odd ) - :nth-child( even ) - ''' - expect(tokens[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[0][1]).toEqual value: 'nth-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[0][3]).toEqual value: '2n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[0][4]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[1][3]).toEqual value: '2n -1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][3]).toEqual value: '-2n+ 1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[3][3]).toEqual value: '-2n - 1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[4][3]).toEqual value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - expect(tokens[5][3]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - expect(tokens[6][3]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[6][4]).toEqual value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - expect(tokens[7][4]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - expect(tokens[7][5]).toEqual value: ' ', scopes: ['source.css', 'meta.selector.css'] - - it 'tokenizes :nth-last-child()', -> - tokens = grammar.tokenizeLines ''' - :nth-last-child(2n) - :nth-last-child( -2n) - :nth-last-child( 2n ) - :nth-last-child(even) - ''' - expect(tokens[0][0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[0][1]).toEqual value: 'nth-last-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[0][2]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[0][3]).toEqual value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[0][4]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[1][4]).toEqual value: '-2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][4]).toEqual value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][6]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[3][3]).toEqual value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css'] - - it 'tokenizes :nth-of-type()', -> - tokens = grammar.tokenizeLines ''' - img:nth-of-type(+n+1) - img:nth-of-type(-n+1) - img:nth-of-type(n+1) - ''' - expect(tokens[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[0][2]).toEqual value: 'nth-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[0][4]).toEqual value: '+n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[0][5]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[1][4]).toEqual value: '-n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][4]).toEqual value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - - it 'tokenizes ::nth-last-of-type()', -> - tokens = grammar.tokenizeLines ''' - h1:nth-last-of-type(-1) - h1:nth-last-of-type(+2) - h1:nth-last-of-type(3) - ''' - expect(tokens[0][1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[0][2]).toEqual value: 'nth-last-of-type', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - expect(tokens[0][3]).toEqual value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[0][4]).toEqual value: '-1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[0][5]).toEqual value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[1][4]).toEqual value: '+2', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - expect(tokens[2][4]).toEqual value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css'] - - describe 'pseudo-elements', -> - # :first-line, :first-letter, :before and :after - it 'tokenizes both : and :: notations for pseudo-elements introduced in CSS 1 and 2', -> - {tokens} = grammar.tokenizeLine '.opening:first-letter' - expect(tokens[0]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'opening', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - expect(tokens[2]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[3]).toEqual value: 'first-letter', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - {tokens} = grammar.tokenizeLine 'q::after' - expect(tokens[0]).toEqual value: 'q', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - it 'tokenizes both : and :: notations for vendor-prefixed pseudo-elements', -> - {tokens} = grammar.tokenizeLine ':-ms-input-placeholder' - expect(tokens[0]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-ms-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - {tokens} = grammar.tokenizeLine '::-webkit-input-placeholder' - expect(tokens[0]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - it 'only tokenizes the :: notation for other pseudo-elements', -> - {tokens} = grammar.tokenizeLine '::selection' - expect(tokens[0]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[1]).toEqual value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - {tokens} = grammar.tokenizeLine ':selection' - expect(tokens[0]).toEqual value: ':selection', scopes: ['source.css', 'meta.selector.css'] - - describe 'compound selectors', -> - it 'tokenizes the combination of type selectors followed by class selectors', -> - {tokens} = grammar.tokenizeLine 'very-custom.class' - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css'] - - it 'tokenizes the combination of type selectors followed by pseudo-classes', -> - {tokens} = grammar.tokenizeLine 'very-custom:hover' - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css'] - - it 'tokenizes the combination of type selectors followed by pseudo-elements', -> - {tokens} = grammar.tokenizeLine 'very-custom::shadow' - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css'] - expect(tokens[2]).toEqual value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css'] - - describe 'property lists (declaration blocks)', -> - it 'tokenizes inline property lists', -> - {tokens} = grammar.tokenizeLine 'div { font-size: inherit; }' - expect(tokens[4]).toEqual value: 'font-size', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[7]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes compact inline property lists', -> - {tokens} = grammar.tokenizeLine 'div{color:inherit;float:left}' - expect(tokens[2]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[4]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[5]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[6]).toEqual value: 'float', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[7]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[8]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes multiple inline property lists', -> - tokens = grammar.tokenizeLines ''' - very-custom { color: inherit } - another-one { display : none ; } - ''' - expect(tokens[0][0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[0][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][7]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[1][0]).toEqual value: 'another-one', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1][4]).toEqual value: 'display', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[1][5]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[1][6]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[1][8]).toEqual value: 'none', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[1][9]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[1][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[1][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes custom properties', -> - {tokens} = grammar.tokenizeLine ':root { --white: #FFF; }' - expect(tokens[5]).toEqual value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css'] - - it 'tokenises commas between property values', -> - {tokens} = grammar.tokenizeLine('a{ text-shadow: a, b; }') - expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - - it 'tokenises superfluous semicolons', -> - lines = grammar.tokenizeLines ''' - .test{ width: 20em;;;;;;;;; - ;;;;;;;;;height: 10em; } - ''' - for i in [0..8] - expect(lines[0][i+9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[1][i]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[1][9]).toEqual value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - - describe 'values', -> - it 'tokenizes color keywords', -> - {tokens} = grammar.tokenizeLine '#jon { color: snow; }' - expect(tokens[8]).toEqual value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css'] - - it 'tokenises RGBA values in hex notation', -> - {tokens} = grammar.tokenizeLine('p{ color: #f030; }') - expect(tokens[6]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(tokens[7]).toEqual value: 'f030', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{ color: #CAFEBABE; }') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(tokens[7]).toEqual value: 'CAFEBABE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{ color: #CAFEBABEF; }') - expect(tokens[6]).toEqual value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - - it 'tokenizes common font names', -> - {tokens} = grammar.tokenizeLine 'p { font-family: Verdana, Helvetica, sans-serif; }' - expect(tokens[7]).toEqual value: 'Verdana', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] - expect(tokens[10]).toEqual value: 'Helvetica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] - expect(tokens[13]).toEqual value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css'] - - it 'tokenizes predefined list style types', -> - {tokens} = grammar.tokenizeLine 'ol.myth { list-style-type: cjk-earthly-branch }' - expect(tokens[9]).toEqual value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css'] - - it 'tokenizes numeric values', -> - {tokens} = grammar.tokenizeLine 'div { font-size: 14px; }' - expect(tokens[7]).toEqual value: '14', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - - it 'does not tokenize invalid numeric values', -> - {tokens} = grammar.tokenizeLine 'div { font-size: test14px; }' - expect(tokens[7]).toEqual value: 'test14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - - {tokens} = grammar.tokenizeLine 'div { font-size: test-14px; }' - expect(tokens[7]).toEqual value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - - it 'tokenizes vendor-prefixed values', -> - {tokens} = grammar.tokenizeLine '.edge { cursor: -webkit-zoom-in; }' - expect(tokens[8]).toEqual value: '-webkit-zoom-in', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] - - {tokens} = grammar.tokenizeLine '.edge { width: -moz-min-content; }' - expect(tokens[8]).toEqual value: '-moz-min-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] - - {tokens} = grammar.tokenizeLine '.edge { display: -ms-grid; }' - expect(tokens[8]).toEqual value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css'] - - it 'tokenizes custom variables', -> - {tokens} = grammar.tokenizeLine 'div { color: var(--primary-color) }' - expect(tokens[9]).toEqual value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - - it 'tokenises numeric values correctly', -> - lines = grammar.tokenizeLines """ - .a { a: 12em } - .a { a: 4.01ex } - .a { a: -456.8ch } - .a { a: 0.0REM } - .a { a: +0.0vh } - .a { a: -0.0vw } - .a { a: .6px } - .a { a: 10e3mm } - .a { a: 10E3cm } - .a { a: -3.4e+2In } - .a { a: -3.4e-2ch } - .a { a: +.5E-2% } - .a { a: -3.4e-2% } - """ - expect(lines[0][8]).toEqual value: '12', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[0][9]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[1][8]).toEqual value: '4.01', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[1][9]).toEqual value: 'ex', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ex.css'] - expect(lines[2][8]).toEqual value: '-456.8', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[2][9]).toEqual value: 'ch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ch.css'] - expect(lines[3][8]).toEqual value: '0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[3][9]).toEqual value: 'REM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.rem.css'] - expect(lines[4][8]).toEqual value: '+0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: 'vh', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.vh.css'] - expect(lines[5][8]).toEqual value: '-0.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[5][9]).toEqual value: 'vw', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.vw.css'] - expect(lines[6][8]).toEqual value: '.6', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[6][9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[7][8]).toEqual value: '10e3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[7][9]).toEqual value: 'mm', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.mm.css'] - expect(lines[8][8]).toEqual value: '10E3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[8][9]).toEqual value: 'cm', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css'] - expect(lines[9][8]).toEqual value: '-3.4e+2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[9][9]).toEqual value: 'In', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.in.css'] - expect(lines[10][8]).toEqual value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[10][9]).toEqual value: 'ch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.ch.css'] - expect(lines[11][8]).toEqual value: '+.5E-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[11][9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[12][8]).toEqual value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(lines[12][9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - - describe 'functional notation', -> - describe 'attr()', -> - it 'tokenises parameters correctly and case-insensitively', -> - {tokens} = grammar.tokenizeLine('a{content:aTTr(data-width px, inherit)}') - expect(tokens[4]).toEqual value: 'aTTr', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: 'data-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(tokens[8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.constant.property-value.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[13]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'matches variables', -> - {tokens} = grammar.tokenizeLine('a{content:ATTR(VAR(--name) px, "N/A")}') - expect(tokens[4]).toEqual value: 'ATTR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: 'VAR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[9]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[11]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(tokens[12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] - expect(tokens[14]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[15]).toEqual value: 'N/A', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] - expect(tokens[16]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[17]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - - describe 'calc()', -> - it 'tokenises calculations', -> - lines = grammar.tokenizeLines """ - a{ - width: calc(3px + -1em); - width: calc(3px - -1em); - width: calc(3px * 2); - width: calc(3px / 2); - } - """ - expect(lines[1][4]).toEqual value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: '3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(lines[1][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[1][9]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(lines[1][11]).toEqual value: '-1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(lines[1][12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[1][13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][9]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(lines[2][11]).toEqual value: '-1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(lines[2][12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[3][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[3][9]).toEqual value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(lines[4][7]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[4][9]).toEqual value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(lines[4][11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - - it 'requires whitespace around + and - operators', -> - {tokens} = grammar.tokenizeLine('a{ width: calc(3px+1em); }') - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] - expect(tokens[11]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(tokens[12]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - - {tokens} = grammar.tokenizeLine('a{ width: calc(3px--1em); height: calc(10-1em);}') - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: '--1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] - expect(tokens[19]).toEqual value: '10', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(tokens[20]).toEqual value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css'] - - it 'does not require whitespace around * and / operators', -> - {tokens} = grammar.tokenizeLine('a{ width: calc(3px*2); }') - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(tokens[11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - - {tokens} = grammar.tokenizeLine('a{ width: calc(3px/2); }') - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[10]).toEqual value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(tokens[11]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - - it 'matches variable expansions inside calculations', -> - {tokens} = grammar.tokenizeLine('.foo { margin-top: calc(var(--gap) + 1px); }') - expect(tokens[8]).toEqual value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[10]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[11]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[12]).toEqual value: '--gap', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[15]).toEqual value: '+', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css'] - expect(tokens[17]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css'] - expect(tokens[18]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[19]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[20]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[22]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'colours', -> - it 'tokenises colour functions correctly', -> - {tokens} = grammar.tokenizeLine('a{ color: rgb(187,255,221); }') - expect(tokens[6]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '187', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[10]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[12]).toEqual value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('a{ color: RGBa( 100%, 0% ,20.17% ,.5 ); }') - expect(tokens[6]).toEqual value: 'RGBa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[9]).toEqual value: '100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[10]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[13]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[14]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[17]).toEqual value: '20.17', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[18]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[20]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[21]).toEqual value: '.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[23]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('a{color:HSL(0, 00100%,50%)}') - expect(tokens[4]).toEqual value: 'HSL', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[9]).toEqual value: '00100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[10]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[12]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[13]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - {tokens} = grammar.tokenizeLine('a{color:HSLa(2,.0%,1%,.7)}') - expect(tokens[4]).toEqual value: 'HSLa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[6]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[8]).toEqual value: '.0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[12]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[13]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[14]).toEqual value: '.7', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'matches variables as colour components', -> - {tokens} = grammar.tokenizeLine('a{ color: RGBA(var(--red), 0% , 20%, .2)}') - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[10]).toEqual value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - - it 'matches comments between colour components', -> - {tokens} = grammar.tokenizeLine('a{ color: rgba(/**/255/*=*/,0,/*2.2%*/51/*,*/0.2)}') - expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[10]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[11]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[12]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(tokens[13]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[14]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[17]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[19]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[20]).toEqual value: '51', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[21]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[22]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(tokens[23]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[24]).toEqual value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css'] - - it 'allows colour components to be split across lines', -> - lines = grammar.tokenizeLines """ - .frost{ - background-color: rgba( - var(--red), /* Red */ - var(--green), /* Green */ - var(--blue), /* Blue */ - /* var(--test), - /**/var(--opacity) /* Transparency */ - ); - } - """ - expect(lines[1][4]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][3]).toEqual value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(lines[2][4]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][8]).toEqual value: ' Red ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[3][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(lines[3][3]).toEqual value: '--green', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(lines[3][5]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][8]).toEqual value: ' Green ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[4][1]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(lines[4][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][3]).toEqual value: '--blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(lines[4][4]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][5]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][8]).toEqual value: ' Blue ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[4][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[5][1]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[5][2]).toEqual value: ' var(--test),', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[6][0]).toEqual value: ' /*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[6][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[6][2]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(lines[6][3]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[6][4]).toEqual value: '--opacity', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(lines[6][5]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[6][7]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[6][8]).toEqual value: ' Transparency ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css'] - expect(lines[6][9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[7][1]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - - describe 'gradients', -> - it 'tokenises linear gradients', -> - {tokens} = grammar.tokenizeLine('a{ background-image: linear-gradient( 45deg, blue, red ); }') - expect(tokens[6]).toEqual value: 'linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[9]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[10]).toEqual value: 'deg', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.deg.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[13]).toEqual value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(tokens[14]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[16]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[19]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('a{ background-image: LINear-graDIEnt( ellipse to left top, blue, red);') - expect(tokens[6]).toEqual value: 'LINear-graDIEnt', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(tokens[9]).toEqual value: 'ellipse', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(tokens[11]).toEqual value: 'to', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] - expect(tokens[13]).toEqual value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(tokens[15]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[18]).toEqual value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(tokens[19]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[21]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css'] - - it 'tokenises radial gradients', -> - {tokens} = grammar.tokenizeLine('a{ background-image: radial-gradient(farthest-corner at 45px 45px , #f00 0%, #00f 100%);}') - expect(tokens[6]).toEqual value: 'radial-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: 'farthest-corner', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(tokens[10]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] - expect(tokens[12]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[13]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[15]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[16]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[20]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(tokens[21]).toEqual value: 'f00', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - expect(tokens[23]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[24]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - - {tokens} = grammar.tokenizeLine('a{ background-image: RADial-gradiENT(16px at 60px 50%,#000 0%, #000 14px, rgba(0,0,0,.3) 18px, transparent 19px)}') - expect(tokens[6]).toEqual value: 'RADial-gradiENT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '16', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[11]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] - expect(tokens[13]).toEqual value: '60', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[14]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[16]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(tokens[17]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(tokens[19]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(tokens[20]).toEqual value: '000', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - expect(tokens[33]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(tokens[34]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[35]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[36]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(tokens[41]).toEqual value: '.3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(tokens[42]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[48]).toEqual value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - - it 'matches gradients that span multiple lines with injected comments', -> - lines = grammar.tokenizeLines """ - a{ - background-image: raDIAL-gradiENT( - ellipse farthest-corner/*@*/at/*@*/470px 47px,/*=== - ========*/#FFFF80 20%, rgba(204, 153, 153, 0.4) 30%,/*))))))))}*/#E6E6FF 60%); } - """ - expect(lines[1][4]).toEqual value: 'raDIAL-gradiENT', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(lines[2][1]).toEqual value: 'ellipse', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(lines[2][3]).toEqual value: 'farthest-corner', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(lines[2][4]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][5]).toEqual value: '@', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[2][6]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[2][7]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'keyword.operator.gradient.css'] - expect(lines[2][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][11]).toEqual value: '470', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css'] - expect(lines[2][12]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(lines[2][16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][17]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[2][18]).toEqual value: '===', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[3][0]).toEqual value: '========', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[3][2]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(lines[3][3]).toEqual value: 'FFFF80', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - expect(lines[3][9]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[3][10]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][20]).toEqual value: '0.4', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[3][21]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][26]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[3][27]).toEqual value: '))))))))}', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[3][28]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[3][29]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(lines[3][30]).toEqual value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - - it 'highlights vendored gradient functions', -> - lines = grammar.tokenizeLines """ - .grad { - background-image: -webkit-linear-gradient(top, /* For Chrome 25 and Safari 6, iOS 6.1, Android 4.3 */ hsl(0, 80%, 70%), #bada55); - background-image: -moz-linear-gradient(top, /* For Firefox (3.6 to 15) */ hsl(0, 80%, 70%), #bada55); - background-image: -o-linear-gradient(top, /* For old Opera (11.1 to 12.0) */ hsl(0, 80%, 70%), #bada55); - } - """ - expect(lines[1][4]).toEqual value: '-webkit-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(lines[1][10]).toEqual value: ' For Chrome 25 and Safari 6, iOS 6.1, Android 4.3 ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[1][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[1][22]).toEqual value: '70', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[1][23]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[1][24]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[1][27]).toEqual value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css'] - expect(lines[1][28]).toEqual value: 'bada55', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css'] - expect(lines[1][29]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][4]).toEqual value: '-moz-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][6]).toEqual value: 'top', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css'] - expect(lines[2][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][10]).toEqual value: ' For Firefox (3.6 to 15) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[2][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[2][14]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][24]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][29]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][4]).toEqual value: '-o-linear-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.function.gradient.css'] - expect(lines[3][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][10]).toEqual value: ' For old Opera (11.1 to 12.0) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css'] - expect(lines[3][13]).toEqual value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[3][14]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - - it 'highlights antique Webkit syntax as deprecated', -> - lines = grammar.tokenizeLines """ - .grad { - background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, - from( rgb(0, 171, 235)), - color-stop(0.5, rgb(255, 255, 255)), - color-stop(0.5, rgb(102, 204, 0)), - to(rgb(255, 255, 255))), - -webkit-gradient(radial, 45 45, 10, 52 50, 30, from(#A7D30C), to(rgba(1,159,98,0)), color-stop(90%, #019F62)), - -webkit-gradient(radial, 105 105, 20, 112 120, 50, from(#ff5f98), to(rgba(255,1,136,0)), color-stop(75%, #ff0188)), - -webkit-gradient(radial, 95 15, 15, 102 20, 40, from(#00c9ff), to(rgba(0,201,255,0)), color-stop(80%, #00b5e2)), - -webkit-gradient(radial, 0 150, 50, 0 140, 90, from(#f4f201), to(rgba(228, 199,0,0)), color-stop(80%, #e4c700)); - } - """ - expect(lines[1][4]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: 'linear', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] - expect(lines[1][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[1][19]).toEqual value: '100', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[1][20]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[2][1]).toEqual value: 'from', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] - expect(lines[2][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][4]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][9]).toEqual value: '171', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[2][10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][1]).toEqual value: 'color-stop', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] - expect(lines[3][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][3]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[3][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][16]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][17]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][1]).toEqual value: 'color-stop', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] - expect(lines[4][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][3]).toEqual value: '0.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[4][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][6]).toEqual value: 'rgb', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[4][7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][8]).toEqual value: '102', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[4][9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][11]).toEqual value: '204', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[4][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css'] - expect(lines[4][14]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'constant.numeric.css'] - expect(lines[4][15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][16]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][17]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[5][1]).toEqual value: 'to', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.function.css'] - expect(lines[5][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[5][12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[5][13]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[5][14]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[5][15]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(lines[6][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] - expect(lines[6][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[6][3]).toEqual value: 'radial', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] - expect(lines[6][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[6][8]).toEqual value: '45', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[6][31]).toEqual value: 'rgba', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'meta.function.color.css', 'support.function.misc.css'] - expect(lines[7][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] - expect(lines[7][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[9][1]).toEqual value: '-webkit-gradient', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'invalid.deprecated.gradient.function.css'] - expect(lines[9][2]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[9][3]).toEqual value: 'radial', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'support.constant.property-value.css'] - expect(lines[9][4]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.separator.list.comma.css'] - expect(lines[9][6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[9][8]).toEqual value: '150', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css'] - expect(lines[9][54]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[9][55]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[10][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'other functions', -> - it 'tokenises basic-shape functions', -> - lines = grammar.tokenizeLines """ - a{ - shape-outside: circle(20em/*=*/at 50% 50%); - shape-outside: inset(1em, 1em, 1em, 1em); - } - """ - expect(lines[1][4]).toEqual value: 'circle', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'support.function.shape.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[1][7]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[1][8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][9]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css'] - expect(lines[1][10]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(lines[1][11]).toEqual value: 'at', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'keyword.operator.shape.css'] - expect(lines[1][13]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[1][14]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[1][16]).toEqual value: '50', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[1][17]).toEqual value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css'] - expect(lines[1][18]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][4]).toEqual value: 'inset', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'support.function.shape.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][6]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[2][7]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[2][8]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][10]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[2][11]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[2][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][14]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[2][15]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[2][16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][18]).toEqual value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css'] - expect(lines[2][19]).toEqual value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(lines[2][20]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'tokenises OpenType feature functions', -> - lines = grammar.tokenizeLines """ - .font{ - font-variant-alternates: stylistic(user-defined-ident); - font-variant-alternates: styleset(user-defined-ident); - font-variant-alternates: character-variant(user-defined-ident); - font-variant-alternates: swash(user-defined-ident); - font-variant-alternates: ornaments(user-defined-ident); - font-variant-alternates: annotation(user-defined-ident); - font-variant-alternates: swash(ident1) annotation(ident2); - } - """ - expect(lines[1][4]).toEqual value: 'stylistic', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[1][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[2][4]).toEqual value: 'styleset', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[2][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[2][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[2][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][4]).toEqual value: 'character-variant', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[3][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[3][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[3][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[4][4]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[4][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[4][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[4][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[5][4]).toEqual value: 'ornaments', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[5][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[5][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[5][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[6][4]).toEqual value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[6][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[6][6]).toEqual value: 'user-defined-ident', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[6][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[7][4]).toEqual value: 'swash', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[7][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[7][6]).toEqual value: 'ident1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[7][7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[7][9]).toEqual value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[7][10]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[7][11]).toEqual value: 'ident2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css'] - expect(lines[7][12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'tokenises image-set()', -> - lines = grammar.tokenizeLines """ - a{ - background-image: image-set( "foo.png" 1x, - "foo-2x.png" 2x, - "foo-print.png" 600dpi ); - } - """ - expect(lines[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(lines[0][1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(lines[1][1]).toEqual value: 'background-image', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[1][4]).toEqual value: 'image-set', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css'] - expect(lines[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(lines[1][7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][8]).toEqual value: 'foo.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] - expect(lines[1][9]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[1][11]).toEqual value: '1x', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.other.density.css'] - expect(lines[1][12]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] - expect(lines[2][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[2][2]).toEqual value: 'foo-2x.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] - expect(lines[2][3]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[2][5]).toEqual value: '2x', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.other.density.css'] - expect(lines[2][6]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css'] - expect(lines[3][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[3][2]).toEqual value: 'foo-print.png', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css'] - expect(lines[3][3]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[3][5]).toEqual value: '600', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css'] - expect(lines[3][6]).toEqual value: 'dpi', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css', 'keyword.other.unit.dpi.css'] - expect(lines[3][8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css'] - expect(lines[3][9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'timing-functions', -> - it 'tokenises them correctly', -> - {tokens} = grammar.tokenizeLine('a{ zoom: cubic-bezier(/**/1.2,/*=*/0,0,0/**/)}') - expect(tokens[6]).toEqual value: 'cubic-bezier', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[10]).toEqual value: '1.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[11]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[15]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[16]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] - expect(tokens[17]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[18]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] - expect(tokens[19]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[20]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[21]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[22]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'highlights the "start" and "end" keywords', -> - {tokens} = grammar.tokenizeLine('a{ before: steps(0, start); after: steps(1, end); }') - expect(tokens[6]).toEqual value: 'steps', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css'] - expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: 'start', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[23]).toEqual value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css'] - - describe 'variables', -> - it 'scopes var() statements as variables', -> - {tokens} = grammar.tokenizeLine('a{color: var(--name)}') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[2]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[5]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[7]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[9]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{color: var( --name )}') - expect(tokens[5]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[6]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[10]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'allows injected comments', -> - {tokens} = grammar.tokenizeLine('a{ color: var( /*=*/ --something ) }') - expect(tokens[6]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[10]).toEqual value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css'] - expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[13]).toEqual value: '--something', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[15]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - - it 'tokenises fallback values', -> - {tokens} = grammar.tokenizeLine('.bar{ width: var(--page-width, /*;;;);*/ 2); }') - expect(tokens[7]).toEqual value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css'] - expect(tokens[8]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[9]).toEqual value: '--page-width', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css'] - expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.separator.list.comma.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: ';;;);', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[16]).toEqual value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'constant.numeric.css'] - expect(tokens[17]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[18]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - - it 'does not tokenise functions with whitespace between name and parameters', -> - {tokens} = grammar.tokenizeLine('a{ p: attr (title); }') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'p', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'attr (title', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[7]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{url:url (s)}') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[2]).toEqual value: 'url', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[4]).toEqual value: 'url (s', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[5]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{content:url ("http://github.com/");}') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[2]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[4]).toEqual value: 'url (', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: 'http://github.com/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{content: url (http://a.pl/)}') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[2]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[3]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[5]).toEqual value: 'url (http://a.pl/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[6]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[7]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - {tokens} = grammar.tokenizeLine('a{ color: rgb (187,255,221); }') - expect(tokens[0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: 'rgb (', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[7]).toEqual value: '187', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(tokens[9]).toEqual value: '255', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[10]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[13]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[15]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'Unicode ranges', -> - it 'tokenises single codepoints', -> - {tokens} = grammar.tokenizeLine('a{ a: U+A5 }') - expect(tokens[6]).toEqual value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - it 'tokenises codepoint ranges', -> - {tokens} = grammar.tokenizeLine('a{ a: U+0025-00FF }') - expect(tokens[6]).toEqual value: 'U+0025', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] - expect(tokens[8]).toEqual value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - {tokens} = grammar.tokenizeLine('a{ unicode-range: u+0-7F }') - expect(tokens[6]).toEqual value: 'u+0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] - expect(tokens[8]).toEqual value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - it 'tokenises wildcard ranges', -> - {tokens} = grammar.tokenizeLine('a{ unicode-range: U+4?? }') - expect(tokens[6]).toEqual value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - {tokens} = grammar.tokenizeLine('a{ unicode-range: U+0025-00FF, U+4?? }') - expect(tokens[6]).toEqual value: 'U+0025', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - expect(tokens[7]).toEqual value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css'] - expect(tokens[8]).toEqual value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - expect(tokens[9]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(tokens[11]).toEqual value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css'] - - describe 'escape sequences', -> - it 'tokenizes escape sequences in single-quoted strings', -> - {tokens} = grammar.tokenizeLine "very-custom { content: '\\c0ffee' }" - - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[4]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[7]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css'] - - it 'tokenizes escape sequences in double-quoted strings', -> - {tokens} = grammar.tokenizeLine 'very-custom { content: "\\c0ffee" }' - - expect(tokens[0]).toEqual value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css'] - expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[4]).toEqual value: 'content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css'] - - it 'tokenises escape sequences in selectors', -> - {tokens} = grammar.tokenizeLine('\\61 \\{ { } \\}') - expect(tokens[0]).toEqual value: '\\61', scopes: ['source.css', 'constant.character.escape.codepoint.css'] - expect(tokens[2]).toEqual value: '\\{', scopes: ['source.css', 'constant.character.escape.css'] - expect(tokens[4]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - expect(tokens[8]).toEqual value: '\\}', scopes: ['source.css', 'constant.character.escape.css'] - - {tokens} = grammar.tokenizeLine('\\61\\ \\. \\@media {}') # Matches <.><@media> - expect(tokens[0]).toEqual value: '\\61', scopes: ['source.css', 'constant.character.escape.codepoint.css'] - expect(tokens[1]).toEqual value: '\\ ', scopes: ['source.css', 'constant.character.escape.css'] - expect(tokens[2]).toEqual value: '\\.', scopes: ['source.css', 'constant.character.escape.css'] - expect(tokens[4]).toEqual value: '\\@', scopes: ['source.css', 'constant.character.escape.css'] - expect(tokens[5]).toEqual value: 'media', scopes: ['source.css', 'meta.selector.css'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[7]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - - it 'tokenises escape sequences in property lists', -> - {tokens} = grammar.tokenizeLine('a { \\77\\69\\64\\74\\68: 20px; }') # Same as writing "width: 20px" - expect(tokens[4]).toEqual value: '\\77', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[5]).toEqual value: '\\69', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[6]).toEqual value: '\\64', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[7]).toEqual value: '\\74', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[8]).toEqual value: '\\68', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css'] - expect(tokens[9]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - - it 'tokenises escape sequences in property values', -> - {tokens} = grammar.tokenizeLine('a { content: \\1F764; }') - expect(tokens[7]).toEqual value: '\\1F764', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.character.escape.codepoint.css'] - expect(tokens[8]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'unclosed strings', -> - it 'highlights an unterminated string as an error', -> - {tokens} = grammar.tokenizeLine("a{ content: 'aaaa") - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[7]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] - - {tokens} = grammar.tokenizeLine('a{ content: "aaaa') - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[7]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] - - it "knows when a string is line-wrapped", -> - lines = grammar.tokenizeLines """ - a{ - content: "aaaaa\\\\\\ - aaa"; color: red; - } - """ - expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][5]).toEqual value: 'aaaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[1][6]).toEqual value: '\\\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.css'] - expect(lines[1][7]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.newline.css'] - expect(lines[2][0]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[2][1]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(lines[2][2]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[2][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - - lines = grammar.tokenizeLines """ - a{ - content: 'aaaaa\\\\\\ - aaa'; color: red; - } - """ - expect(lines[1][4]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][5]).toEqual value: 'aaaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css'] - expect(lines[1][6]).toEqual value: '\\\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.css'] - expect(lines[1][7]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.newline.css'] - expect(lines[2][0]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css'] - expect(lines[2][1]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css'] - expect(lines[2][2]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[2][4]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - - it 'highlights escape sequences inside invalid strings', -> - {tokens} = grammar.tokenizeLine('a{ content: "aaa\\"aa') - expect(tokens[6]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[7]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] - expect(tokens[8]).toEqual value: '\\"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css'] - expect(tokens[9]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] - - {tokens} = grammar.tokenizeLine("a{ content: 'aaa\\'aa") - expect(tokens[6]).toEqual value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css'] - expect(tokens[7]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] - expect(tokens[8]).toEqual value: "\\'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css'] - expect(tokens[9]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css'] - - it 'highlights unclosed lines in line-wrapped strings', -> - lines = grammar.tokenizeLines """ - a{ - content: "aaa\\"aa\\ - aaaa - aaaa; color: red; - } - """ - expect(lines[1][4]).toEqual value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(lines[1][5]).toEqual value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[1][6]).toEqual value: '\\"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.css'] - expect(lines[1][7]).toEqual value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css'] - expect(lines[1][8]).toEqual value: '\\', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.newline.css'] - expect(lines[2][0]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css'] - expect(lines[3][0]).toEqual value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(lines[3][1]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[3][3]).toEqual value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(lines[3][4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(lines[3][6]).toEqual value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css'] - expect(lines[3][7]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(lines[4][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'comments', -> - it 'tokenises comments inside @import statements', -> - {tokens} = grammar.tokenizeLine('@import /* url("name"); */ "1.css";') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[4]).toEqual value: ' url("name"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[5]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[8]).toEqual value: '1.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css'] - expect(tokens[9]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[10]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import/*";"*/ url("2.css");') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '";"', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[6]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[7]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[8]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[9]).toEqual value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[10]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[11]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[12]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - {tokens} = grammar.tokenizeLine('@import url("3.css") print /* url(";"); */;') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css'] - expect(tokens[3]).toEqual value: 'url', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'support.function.url.css'] - expect(tokens[4]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[5]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css'] - expect(tokens[6]).toEqual value: '3.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css'] - expect(tokens[7]).toEqual value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css'] - expect(tokens[8]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[10]).toEqual value: 'print', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css'] - expect(tokens[12]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[13]).toEqual value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css'] - expect(tokens[14]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[15]).toEqual value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css'] - - it 'tokenises comments inside @font-face statements', -> - {tokens} = grammar.tokenizeLine('@font-face/*"{;}"*/{}') - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'font-face', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: '"{;}"', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[5]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[6]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes comments before media queries', -> - {tokens} = grammar.tokenizeLine '/* comment */ @media' - - expect(tokens[0]).toEqual value: '/*', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[1]).toEqual value: ' comment ', scopes: ['source.css', 'comment.block.css'] - expect(tokens[2]).toEqual value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[4]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[5]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - - it 'tokenizes comments after media queries', -> - {tokens} = grammar.tokenizeLine '@media/* comment */ ()' - - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[2]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[3]).toEqual value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[4]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - - it 'tokenizes comments inside query lists', -> - {tokens} = grammar.tokenizeLine '@media (max-height: 40em/* comment */)' - - expect(tokens[0]).toEqual value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css'] - expect(tokens[1]).toEqual value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css'] - expect(tokens[3]).toEqual value: '(', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.begin.bracket.round.css'] - expect(tokens[4]).toEqual value: 'max-height', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.property-name.media.css'] - expect(tokens[5]).toEqual value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css'] - expect(tokens[7]).toEqual value: '40', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css'] - expect(tokens[8]).toEqual value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css'] - expect(tokens[9]).toEqual value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[10]).toEqual value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css'] - expect(tokens[11]).toEqual value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[12]).toEqual value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css'] - - it 'tokenizes inline comments', -> - {tokens} = grammar.tokenizeLine 'section {border:4px/*padding:1px*/}' - - expect(tokens[0]).toEqual value: 'section', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[3]).toEqual value: 'border', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[4]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[5]).toEqual value: '4', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[6]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[7]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(tokens[8]).toEqual value: 'padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] - expect(tokens[9]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - expect(tokens[10]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it 'tokenizes multi-line comments', -> - lines = grammar.tokenizeLines """ - section { - border:4px /*1px; - padding:1px*/ - } - """ - - expect(lines[1][5]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(lines[1][6]).toEqual value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css'] - expect(lines[1][7]).toEqual value: '1px;', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] - - expect(lines[2][0]).toEqual value: ' padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css'] - expect(lines[2][1]).toEqual value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css'] - - expect(lines[3][0]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - describe 'Animations', -> - it 'does not confuse animation names with predefined keywords', -> - tokens = grammar.tokenizeLines ''' - .animated { - animation-name: orphan-black; - animation-name: line-scale; - } - ''' - expect(tokens[1][4]).toEqual value: 'orphan-black', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[2][4]).toEqual value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - - describe 'Transforms', -> - it 'tokenizes transform functions', -> - tokens = grammar.tokenizeLines ''' - .transformed { - transform: matrix(0, 1.5, -1.5, 0, 0, 100px); - transform: rotate(90deg) translateX(100px) scale(1.5); - } - ''' - expect(tokens[1][1]).toEqual value: 'transform', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[1][2]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[1][4]).toEqual value: 'matrix', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] - expect(tokens[1][5]).toEqual value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.begin.bracket.round.css'] - expect(tokens[1][6]).toEqual value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[1][7]).toEqual value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css'] - expect(tokens[1][12]).toEqual value: '-1.5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[1][22]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[1][23]).toEqual value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.end.bracket.round.css'] - expect(tokens[2][4]).toEqual value: 'rotate', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] - expect(tokens[2][10]).toEqual value: 'translateX', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] - expect(tokens[2][16]).toEqual value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css'] - - describe "performance regressions", -> - it "does not hang when tokenizing invalid input preceding an equals sign", -> - grammar = atom.grammars.grammarForScopeName('source.css') - start = Date.now() - grammar.tokenizeLine(' - start = Date.now() - grammar.tokenizeLines """ - - [}~#{'ÁÂÃÄÅÆÇÈÊËÍÎ'.repeat(100)} - - """ - expect(Date.now() - start).toBeLessThan(5000) - - describe "firstLineMatch", -> - it "recognises Emacs modelines", -> - valid = """ - #-*- CSS -*- - #-*- mode: CSS -*- - /* -*-css-*- */ - // -*- CSS -*- - /* -*- mode:CSS -*- */ - // -*- font:bar;mode:CSS -*- - // -*- font:bar;mode:CSS;foo:bar; -*- - // -*-font:mode;mode:CSS-*- - // -*- foo:bar mode: css bar:baz -*- - " -*-foo:bar;mode:css;bar:foo-*- "; - " -*-font-mode:foo;mode:css;foo-bar:quux-*-" - "-*-font:x;foo:bar; mode : CsS; bar:foo;foooooo:baaaaar;fo:ba;-*-"; - "-*- font:x;foo : bar ; mode : cSS ; bar : foo ; foooooo:baaaaar;fo:ba-*-"; - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - /* --*css-*- */ - /* -*-- CSS -*- - /* -*- -- CSS -*- - /* -*- CSS -;- -*- - // -*- CCSS -*- - // -*- CSS; -*- - // -*- css-stuff -*- - /* -*- model:css -*- - /* -*- indent-mode:css -*- - // -*- font:mode;CSS -*- - // -*- mode: -*- CSS - // -*- mode: I-miss-plain-old-css -*- - // -*-font:mode;mode:css--*- - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - it "recognises Vim modelines", -> - valid = """ - vim: se filetype=css: - # vim: se ft=css: - # vim: set ft=CSS: - # vim: set filetype=CSS: - # vim: ft=CSS - # vim: syntax=CSS - # vim: se syntax=css: - # ex: syntax=CSS - # vim:ft=css - # vim600: ft=css - # vim>600: set ft=css: - # vi:noai:sw=3 ts=6 ft=CSS - # vi::::::::::noai:::::::::::: ft=CSS - # vim:ts=4:sts=4:sw=4:noexpandtab:ft=cSS - # vi:: noai : : : : sw =3 ts =6 ft =Css - # vim: ts=4: pi sts=4: ft=CSS: noexpandtab: sw=4: - # vim: ts=4 sts=4: ft=css noexpandtab: - # vim:noexpandtab sts=4 ft=css ts=4 - # vim:noexpandtab:ft=css - # vim:ts=4:sts=4 ft=css:noexpandtab:\x20 - # vim:noexpandtab titlestring=hi\|there\\\\ ft=css ts=4 - """ - for line in valid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull() - - invalid = """ - ex: se filetype=css: - _vi: se filetype=CSS: - vi: se filetype=CSS - # vim set ft=css3 - # vim: soft=css - # vim: clean-syntax=css: - # vim set ft=css: - # vim: setft=CSS: - # vim: se ft=css backupdir=tmp - # vim: set ft=css set cmdheight=1 - # vim:noexpandtab sts:4 ft:CSS ts:4 - # vim:noexpandtab titlestring=hi\\|there\\ ft=CSS ts=4 - # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=CSS ts=4 - """ - for line in invalid.split /\n/ - expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull() - - describe "Missing supported properties regressions", -> - it "recognises place-items property as supported", -> - tokens = grammar.tokenizeLines 'a { place-items: center center; }' - expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][4]).toEqual value: 'place-items', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "recognises place-self property as supported", -> - tokens = grammar.tokenizeLines 'a { place-self: center center; }' - expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][4]).toEqual value: 'place-self', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "recognises place-content property as supported", -> - tokens = grammar.tokenizeLines 'a { place-content: center center; }' - expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][4]).toEqual value: 'place-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][7]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][8]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css'] - expect(tokens[0][9]).toEqual value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css'] - expect(tokens[0][10]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[0][11]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][12]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] - - it "recognises row-gap property as supported", -> - tokens = grammar.tokenizeLines 'a { row-gap: 5px; }' - expect(tokens[0][0]).toEqual value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css'] - expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.css'] - expect(tokens[0][2]).toEqual value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css'] - expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][4]).toEqual value: 'row-gap', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css'] - expect(tokens[0][5]).toEqual value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css'] - expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][7]).toEqual value: '5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css'] - expect(tokens[0][8]).toEqual value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css'] - expect(tokens[0][9]).toEqual value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css'] - expect(tokens[0][10]).toEqual value: ' ', scopes: ['source.css', 'meta.property-list.css'] - expect(tokens[0][11]).toEqual value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css'] diff --git a/packages/language-css/spec/css-spec.js b/packages/language-css/spec/css-spec.js index c092ee0070..20f1373cf0 100644 --- a/packages/language-css/spec/css-spec.js +++ b/packages/language-css/spec/css-spec.js @@ -1,10 +1,4 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS205: Consider reworking code to avoid use of IIFEs - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + describe('CSS grammar', function() { let grammar = null; @@ -13,36 +7,36 @@ describe('CSS grammar', function() { waitsForPromise(() => atom.packages.activatePackage('language-css')); - return runs(() => grammar = atom.grammars.grammarForScopeName('source.css')); + runs(() => grammar = atom.grammars.grammarForScopeName('source.css')); }); it('parses the grammar', function() { expect(grammar).toBeTruthy(); - return expect(grammar.scopeName).toBe('source.css'); + expect(grammar.scopeName).toBe('source.css'); }); describe('selectors', function() { it('tokenizes type selectors', function() { const {tokens} = grammar.tokenizeLine('p {}'); - return expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); + expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); }); it('tokenizes the universal selector', function() { const {tokens} = grammar.tokenizeLine('*'); - return expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); + expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); }); it('tokenises combinators', function() { const {tokens} = grammar.tokenizeLine('a > b + * ~ :not(.nah)'); expect(tokens[2]).toEqual({value: '>', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); expect(tokens[6]).toEqual({value: '+', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); - return expect(tokens[10]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); + expect(tokens[10]).toEqual({value: '~', scopes: ['source.css', 'meta.selector.css', 'keyword.operator.combinator.css']}); }); it('highlights deprecated combinators', function() { const {tokens} = grammar.tokenizeLine('.sooo /deep/ >>>_.>>>'); expect(tokens[3]).toEqual({value: '/deep/', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); - return expect(tokens[5]).toEqual({value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); + expect(tokens[5]).toEqual({value: '>>>', scopes: ['source.css', 'invalid.deprecated.combinator.css']}); }); it('tokenizes complex selectors', function() { @@ -129,41 +123,41 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(lines[4][12]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[4][13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); expect(lines[4][15]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(lines[4][17]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][17]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); describe('custom elements (as type selectors)', function() { it('only tokenizes identifiers beginning with [a-z]', function() { const {tokens} = grammar.tokenizeLine('pearl-1941 1941-pearl -pearl-1941'); expect(tokens[0]).toEqual({value: 'pearl-1941', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); - return expect(tokens[1]).toEqual({value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[1]).toEqual({value: ' 1941-pearl -pearl-1941', scopes: ['source.css', 'meta.selector.css']}); }); it('tokenizes custom elements containing non-ASCII letters', function() { const {tokens} = grammar.tokenizeLine('pokémon-ピカチュウ'); - return expect(tokens[0]).toEqual({value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); + expect(tokens[0]).toEqual({value: 'pokémon-ピカチュウ', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); }); it('does not tokenize identifiers containing [A-Z]', function() { const {tokens} = grammar.tokenizeLine('Basecamp-schedule basecamp-Schedule'); - return expect(tokens[0]).toEqual({value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[0]).toEqual({value: 'Basecamp-schedule basecamp-Schedule', scopes: ['source.css', 'meta.selector.css']}); }); it('does not tokenize identifiers containing no hyphens', function() { const {tokens} = grammar.tokenizeLine('halo_night'); - return expect(tokens[0]).toEqual({value: 'halo_night', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[0]).toEqual({value: 'halo_night', scopes: ['source.css', 'meta.selector.css']}); }); it('does not tokenise identifiers following an @ symbol', function() { const {tokens} = grammar.tokenizeLine('@some-weird-new-feature'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); - return expect(tokens[1]).toEqual({value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + expect(tokens[1]).toEqual({value: 'some-weird-new-feature', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); }); - return it('does not tokenise identifiers in unfamiliar functions', function() { + it('does not tokenise identifiers in unfamiliar functions', function() { const {tokens} = grammar.tokenizeLine('some-edgy-new-function()'); expect(tokens[0]).toEqual({value: 'some-edgy-new-function(', scopes: ['source.css', 'meta.selector.css']}); - return expect(tokens[1]).toEqual({value: ')', scopes: ['source.css']}); + expect(tokens[1]).toEqual({value: ')', scopes: ['source.css']}); }); }); @@ -172,7 +166,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], const {tokens} = grammar.tokenizeLine('[title]'); expect(tokens[0]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[1]).toEqual({value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - return expect(tokens[2]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[2]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes attribute selectors with identifier values', function() { @@ -181,7 +175,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[1]).toEqual({value: 'hreflang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[2]).toEqual({value: '|=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); expect(tokens[3]).toEqual({value: 'fr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); - return expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes attribute selectors with string values', function() { @@ -192,7 +186,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'http://www.w3.org/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names with wildcard prefix', function() { @@ -201,7 +195,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[1]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); expect(tokens[2]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); expect(tokens[3]).toEqual({value: 'title', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - return expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[4]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names with namespace prefix', function() { @@ -212,7 +206,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: 'origin', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[4]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); expect(tokens[5]).toEqual({value: 'radiation', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); - return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenizes CSS qualified attribute names without namespace prefix', function() { @@ -224,7 +218,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[5]).toEqual({value: '75', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises compound ID/attribute selectors', function() { @@ -241,7 +235,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[2]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); expect(tokens[3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[4]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); - return expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); }); it('tokenises compound class/attribute selectors', function() { @@ -259,7 +253,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(tokens[4]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[5]).toEqual({value: 'id', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('allows whitespace to be inserted between tokens', function() { @@ -276,7 +270,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[10]).toEqual({value: '%%', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css']}); expect(tokens[11]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[12]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - return expect(tokens[13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[13]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences inside attribute selectors', function() { @@ -286,7 +280,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: '0', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[5]).toEqual({value: '\\]', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); expect(tokens[6]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); - return expect(tokens[10]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[10]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences inside namespace prefixes', function() { @@ -300,7 +294,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[8]).toEqual({value: 'It', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); expect(tokens[9]).toEqual({value: '\\?', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css', 'constant.character.escape.css']}); expect(tokens[10]).toEqual({value: '=', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'keyword.operator.pattern.css']}); - return expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises comments inside attribute selectors', function() { @@ -311,7 +305,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[3]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[5]).toEqual({value: 'lang', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); - return expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[6]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises quoted strings in attribute selectors', function() { @@ -343,7 +337,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[24]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css']}); expect(tokens[25]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); expect(tokens[26]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - return expect(tokens[27]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[27]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises unquoted strings in attribute selectors', function() { @@ -357,7 +351,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); expect(tokens[5]).toEqual({value: '0xDEADCAFE=|~BEEFBABE', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); - return expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[7]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); it('tokenises escape sequences in unquoted strings', function() { @@ -371,7 +365,7 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[12]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css', 'constant.character.escape.css']}); expect(tokens[13]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[14]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); - return expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises the ignore-case modifier at the end of a selector', function() { @@ -398,10 +392,10 @@ a::last-of-type,/*Comment*/::selection > html[lang^=en-AU], expect(tokens[54]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'string.unquoted.attribute-value.css']}); expect(tokens[55]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css']}); expect(tokens[56]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); - return expect(tokens[57]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(tokens[57]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); - return it('tokenises attribute selectors spanning multiple lines', function() { + it('tokenises attribute selectors spanning multiple lines', function() { let lines = grammar.tokenizeLines(`\ span[ \\x20{2} @@ -455,7 +449,7 @@ i]\ expect(lines[3][0]).toEqual({value: ' |', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css']}); expect(lines[4][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[5][0]).toEqual({value: 'i', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'storage.modifier.ignore-case.css']}); - return expect(lines[5][1]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); + expect(lines[5][1]).toEqual({value: ']', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.end.bracket.square.css']}); }); }); @@ -467,19 +461,19 @@ i]\ ({tokens} = grammar.tokenizeLine('.スポンサー')); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[1]).toEqual({value: 'スポンサー', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes a class selector consisting of two hypens', function() { const {tokens} = grammar.tokenizeLine('.--'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[1]).toEqual({value: '--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes class selectors consisting of one (valid) character', function() { const {tokens} = grammar.tokenizeLine('._'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[1]).toEqual({value: '_', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenises class selectors starting with an escape sequence', function() { @@ -488,7 +482,7 @@ i]\ expect(tokens[1]).toEqual({value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css']}); expect(tokens[2]).toEqual({value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.codepoint.css']}); expect(tokens[3]).toEqual({value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); - return expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises class selectors ending with an escape sequence', function() { @@ -498,35 +492,35 @@ i]\ expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css']}); expect(tokens[3]).toEqual({value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(tokens[4]).toEqual({value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'constant.character.escape.css']}); - return expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it contains unescaped ASCII punctuation or symbols other than "-" and "_"', function() { const {tokens} = grammar.tokenizeLine('.B&W{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'B&W', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it starts with ASCII digits ([0-9])', function() { const {tokens} = grammar.tokenizeLine('.666{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks a class invalid if it starts with "-" followed by ASCII digits', function() { const {tokens} = grammar.tokenizeLine('.-911-{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); - return it('marks a class invalid if it consists of only one hyphen', function() { + it('marks a class invalid if it consists of only one hyphen', function() { const {tokens} = grammar.tokenizeLine('.-{'); expect(tokens[0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); }); @@ -534,53 +528,53 @@ i]\ it('tokenizes id selectors consisting of ASCII letters', function() { const {tokens} = grammar.tokenizeLine('#unicorn'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[1]).toEqual({value: 'unicorn', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors containing non-ASCII letters', function() { const {tokens} = grammar.tokenizeLine('#洪荒之力'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[1]).toEqual({value: '洪荒之力', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors containing [0-9], "-", or "_"', function() { const {tokens} = grammar.tokenizeLine('#_zer0-day'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[1]).toEqual({value: '_zer0-day', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('tokenizes id selectors beginning with two hyphens', function() { const {tokens} = grammar.tokenizeLine('#--d3bug--'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); + expect(tokens[1]).toEqual({value: '--d3bug--', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); }); it('marks an id invalid if it contains ASCII punctuation or symbols other than "-" and "_"', function() { const {tokens} = grammar.tokenizeLine('#sort!{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'sort!', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it starts with ASCII digits ([0-9])', function() { const {tokens} = grammar.tokenizeLine('#666{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '666', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it starts with "-" followed by ASCII digits', function() { const {tokens} = grammar.tokenizeLine('#-911-{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-911-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('marks an id invalid if it consists of one hyphen only', function() { const {tokens} = grammar.tokenizeLine('#-{'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: '-', scopes: ['source.css', 'meta.selector.css', 'invalid.illegal.bad-identifier.css']}); - return expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises ID selectors starting with an escape sequence', function() { @@ -589,17 +583,17 @@ i]\ expect(tokens[1]).toEqual({value: '\\33', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css']}); expect(tokens[2]).toEqual({value: '\\44', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.codepoint.css']}); expect(tokens[3]).toEqual({value: '-model', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); - return expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); - return it('tokenises ID selectors ending with an escape sequence', function() { + it('tokenises ID selectors ending with an escape sequence', function() { const {tokens} = grammar.tokenizeLine('#la\\{tex\\} {'); expect(tokens[0]).toEqual({value: '#', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'la', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[2]).toEqual({value: '\\{', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css']}); expect(tokens[3]).toEqual({value: 'tex', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css']}); expect(tokens[4]).toEqual({value: '\\}', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.id.css', 'constant.character.escape.css']}); - return expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); }); @@ -611,7 +605,7 @@ i]\ expect(tokens[2]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[3]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[4]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises anonymous namespace prefixes', function() { @@ -643,7 +637,7 @@ i]\ expect(tokens[1]).toEqual({value: '[', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.definition.entity.begin.bracket.square.css']}); expect(tokens[2]).toEqual({value: 'svg', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.namespace-prefix.css']}); expect(tokens[3]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'punctuation.separator.css']}); - return expect(tokens[4]).toEqual({value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); + expect(tokens[4]).toEqual({value: 'attr', scopes: ['source.css', 'meta.selector.css', 'meta.attribute-selector.css', 'entity.other.attribute-name.css']}); }); it('tokenises the "no-namespace" prefix', function() { @@ -651,10 +645,10 @@ i]\ expect(tokens[0]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.css']}); expect(tokens[1]).toEqual({value: 'h1', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[3]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[5]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it("doesn't tokenise prefixes without a selector", function() { + it("doesn't tokenise prefixes without a selector", function() { let {tokens} = grammar.tokenizeLine('*| { }'); expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css']}); @@ -666,7 +660,7 @@ i]\ expect(tokens[0]).toEqual({value: '*', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.wildcard.css']}); expect(tokens[1]).toEqual({value: '|', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[4]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -688,10 +682,10 @@ i]\ expect(lines[0][1]).toEqual({value: ' Not the first line ', scopes: ['source.css', 'comment.block.css']}); expect(lines[0][2]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[1][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); - return expect(lines[1][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); + expect(lines[1][1]).toEqual({value: 'charset', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); }); - return it('highlights invalid @charset statements', function() { + it('highlights invalid @charset statements', function() { let lines = grammar.tokenizeLines(" @charset 'US-ASCII';"); expect(lines[0][0]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.leading-whitespace.charset.css']}); expect(lines[0][1]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.charset.css', 'keyword.control.at-rule.charset.css', 'punctuation.definition.keyword.css']}); @@ -741,7 +735,7 @@ i]\ lines = grammar.tokenizeLines("@CHARSET 'US-ASCII';"); expect(lines[0][0]).toEqual({value: '@CHARSET', scopes: ['source.css', 'meta.at-rule.charset.css', 'invalid.illegal.not-lowercase.charset.css']}); expect(lines[0][1]).toEqual({value: " 'US-ASCII'", scopes: ['source.css', 'meta.at-rule.charset.css']}); - return expect(lines[0][2]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); + expect(lines[0][2]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.charset.css', 'punctuation.terminator.rule.css']}); }); }); @@ -769,7 +763,7 @@ i]\ ({tokens} = grammar.tokenizeLine("@import 'file.css';")); expect(tokens[3]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css']}); - return expect(tokens[5]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[5]).toEqual({value: "'", scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); }); it("doesn't let injected comments impact parameter matching", function() { @@ -793,7 +787,7 @@ i]\ expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[6]).toEqual({value: '2.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('correctly handles word boundaries', function() { @@ -809,7 +803,7 @@ i]\ expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'import-file', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); expect(tokens[2]).toEqual({value: '.css', scopes: ['source.css', 'meta.at-rule.header.css']}); - return expect(tokens[3]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css']}); + expect(tokens[3]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.header.css', 'punctuation.terminator.rule.css']}); }); it('matches a URL that starts on the next line', function() { @@ -823,7 +817,7 @@ i]\ expect(lines[1][3]).toEqual({value: 'file.css', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(lines[1][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[1][5]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('matches comments inside query lists', function() { @@ -841,7 +835,7 @@ i]\ expect(tokens[13]).toEqual({value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[16]).toEqual({value: 'all', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.media.css']}); - return expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('highlights deprecated media types', function() { @@ -852,10 +846,10 @@ i]\ expect(tokens[4]).toEqual({value: 'astral.css', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css']}); expect(tokens[5]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.import.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[7]).toEqual({value: 'projection', scopes: ['source.css', 'meta.at-rule.import.css', 'invalid.deprecated.constant.media.css']}); - return expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); - return it('highlights media features in query lists', function() { + it('highlights media features in query lists', function() { const {tokens} = grammar.tokenizeLine('@import url(\'landscape.css\') screen and (orientation:landscape);'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'import', scopes: ['source.css', 'meta.at-rule.import.css', 'keyword.control.at-rule.import.css']}); @@ -872,7 +866,7 @@ i]\ expect(tokens[16]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.separator.key-value.css']}); expect(tokens[17]).toEqual({value: 'landscape', scopes: ['source.css', 'meta.at-rule.import.css', 'support.constant.property-value.css']}); expect(tokens[18]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.definition.parameters.end.bracket.round.css']}); - return expect(tokens[19]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[19]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); }); @@ -904,7 +898,7 @@ i]\ expect(tokens[14]).toEqual({value: 'em', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[16]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights deprecated media types', function() { @@ -918,7 +912,7 @@ i]\ expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[10]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights vendored media features', function() { @@ -968,7 +962,7 @@ i]\ expect(tokens[4]).toEqual({value: 'mso-page-size', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.type.vendored.property-name.media.css']}); expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: 'wide', scopes: ['source.css', 'meta.at-rule.media.header.css']}); - return expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[7]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); }); it('tokenises @media immediately following a closing brace', function() { @@ -998,7 +992,7 @@ i]\ expect(tokens[14]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); expect(tokens[15]).toEqual({value: 'h2', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[17]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises level 4 media-query syntax', function() { @@ -1012,7 +1006,7 @@ i]\ expect(lines[0][6]).toEqual({value: '>=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); expect(lines[1][6]).toEqual({value: '<=', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); expect(lines[2][6]).toEqual({value: '>', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); - return expect(lines[3][6]).toEqual({value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); + expect(lines[3][6]).toEqual({value: '<', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.operator.comparison.css']}); }); it('tokenises comments between media types', function() { @@ -1035,10 +1029,10 @@ i]\ expect(tokens[19]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[20]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[21]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); - return it('tokenises comments between media features', function() { + it('tokenises comments between media features', function() { const {tokens} = grammar.tokenizeLine('@media/*=*/(max-width:/**/37.5em)/*=*/and/*=*/(/*=*/min-height/*:*/:/*=*/1.2em/*;*/){}'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); @@ -1079,7 +1073,7 @@ i]\ expect(tokens[36]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[37]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(tokens[38]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[39]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[39]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); }); @@ -1147,7 +1141,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[3][23]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.media.header.css', 'constant.numeric.css']}); expect(lines[3][24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); expect(lines[3][26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(lines[3][28]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(lines[3][28]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('highlights invalid commas', function() { @@ -1164,7 +1158,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[3]).toEqual({value: ', ,', scopes: ['source.css', 'meta.at-rule.media.header.css', 'invalid.illegal.comma.css']}); expect(tokens[4]).toEqual({value: 'screen', scopes: ['source.css', 'meta.at-rule.media.header.css', 'support.constant.media.css']}); expect(tokens[6]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.begin.bracket.curly.css']}); - return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.media.body.css', 'punctuation.section.media.end.bracket.curly.css']}); }); it('allows spaces inside ratio values', function() { @@ -1178,7 +1172,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[21]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); expect(tokens[22]).toEqual({value: '/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'keyword.operator.arithmetic.css']}); expect(tokens[23]).toEqual({value: ' ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css']}); - return expect(tokens[24]).toEqual({value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); + expect(tokens[24]).toEqual({value: '17', scopes: ['source.css', 'meta.at-rule.media.header.css', 'meta.ratio.css', 'constant.numeric.css']}); }); describe('@keyframes', function() { @@ -1229,7 +1223,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[4][9]).toEqual({value: 'px', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(lines[4][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[4][12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1250,7 +1244,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][0]).toEqual({value: ' { Nah { margin-top: 2em; }', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css']}); expect(lines[2][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[2][1]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.begin.bracket.curly.css']}); - return expect(lines[2][3]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); + expect(lines[2][3]).toEqual({value: 'from', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); }); it('matches offset keywords case-insensitively', function() { @@ -1266,22 +1260,22 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[13]).toEqual({value: 'To', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.css']}); expect(tokens[15]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); expect(tokens[16]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); + expect(tokens[18]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); }); it('matches percentile offsets', function() { const {tokens} = grammar.tokenizeLine('@keyframes identifier { -50.2% } @keyframes ident2 { .25%}'); expect(tokens[7]).toEqual({value: '-50.2%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); - return expect(tokens[18]).toEqual({value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); + expect(tokens[18]).toEqual({value: '.25%', scopes: ['source.css', 'meta.at-rule.keyframes.body.css', 'entity.other.keyframe-offset.percentage.css']}); }); - return it('highlights escape sequences inside identifiers', function() { + it('highlights escape sequences inside identifiers', function() { const {tokens} = grammar.tokenizeLine('@keyframes A\\1F602Z'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'keyframes', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'keyword.control.at-rule.keyframes.css']}); expect(tokens[3]).toEqual({value: 'A', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); expect(tokens[4]).toEqual({value: '\\1F602', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css', 'constant.character.escape.codepoint.css']}); - return expect(tokens[5]).toEqual({value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); + expect(tokens[5]).toEqual({value: 'Z', scopes: ['source.css', 'meta.at-rule.keyframes.header.css', 'variable.parameter.keyframe-list.css']}); }); }); @@ -1299,7 +1293,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[9]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); expect(tokens[10]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[11]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); - return expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('matches logical operators', function() { @@ -1311,7 +1305,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati ); expect(lines[0][3]).toEqual({value: 'not', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.not.css']}); expect(lines[1][11]).toEqual({value: 'and', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.and.css']}); - return expect(lines[2][11]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); + expect(lines[2][11]).toEqual({value: 'or', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'keyword.operator.logical.feature.or.css']}); }); it('matches custom variables in feature queries', function() { @@ -1320,7 +1314,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[4]).toEqual({value: '--foo', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'variable.css']}); expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.separator.key-value.css']}); expect(tokens[7]).toEqual({value: 'green', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); - return expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); + expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); }); it("doesn't mistake brackets in string literals for feature queries", function() { @@ -1348,7 +1342,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][10]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[1][11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[1][13]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('tokenises multiple feature queries', function() { @@ -1374,7 +1368,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[23]).toEqual({value: 'run-in', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[24]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); expect(tokens[25]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'meta.feature-query.css', 'punctuation.definition.condition.end.bracket.round.css']}); - return expect(tokens[26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); + expect(tokens[26]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); }); it('embeds rulesets and other at-rules', function() { @@ -1475,7 +1469,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[13][10]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[13][12]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); expect(lines[14][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.at-rule.keyframes.body.css', 'punctuation.section.keyframes.end.bracket.curly.css']}); - return expect(lines[15][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(lines[15][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1510,10 +1504,10 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[1][20]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css']}); expect(lines[1][21]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.supports.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[1][22]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.begin.bracket.curly.css']}); - return expect(lines[1][23]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(lines[1][23]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); - return it('matches feature queries across multiple lines', function() { + it('matches feature queries across multiple lines', function() { const lines = grammar.tokenizeLines(`\ @supports (box-shadow: 0 0 2px rgba(0,0,0,.5) inset) or @@ -1582,7 +1576,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(lines[5][3]).toEqual({value: 'noticebox', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); expect(lines[5][5]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); expect(lines[5][7]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); + expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.supports.body.css', 'punctuation.section.supports.end.bracket.curly.css']}); }); }); @@ -1619,7 +1613,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[6]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[8]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(tokens[9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it("doesn't confuse a prefix of 'url' as a function", function() { @@ -1633,7 +1627,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[8]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(tokens[9]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(tokens[11]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('permits injected comments between tokens', function() { @@ -1653,7 +1647,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[13]).toEqual({value: '=', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('allows no spaces between "@namespace" and quoted URLs', function() { @@ -1663,7 +1657,7 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[2]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[3]).toEqual({value: 'XML', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css']}); expect(tokens[4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(tokens[5]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); it('tokenises escape sequences in prefixes', function() { @@ -1671,10 +1665,10 @@ only speech and (min-width: 10em), /* wat */ (-webkit-min-device-pixel-rati expect(tokens[3]).toEqual({value: 'pre', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); expect(tokens[4]).toEqual({value: '\\ ', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css', 'constant.character.escape.css']}); expect(tokens[5]).toEqual({value: 'fix', scopes: ['source.css', 'meta.at-rule.namespace.css', 'entity.name.function.namespace-prefix.css']}); - return expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); + expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); }); - return it('allows arguments to span multiple lines', function() { + it('allows arguments to span multiple lines', function() { let lines = grammar.tokenizeLines(`\ @namespace prefix"XML";\ @@ -1705,7 +1699,7 @@ url("http://a.bc/");\ expect(lines[4][3]).toEqual({value: 'http://a.bc/', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css']}); expect(lines[4][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[4][5]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.namespace.css', 'meta.function.url.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(lines[4][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); + expect(lines[4][6]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.namespace.css', 'punctuation.terminator.rule.css']}); }); }); @@ -1718,7 +1712,7 @@ url("http://a.bc/");\ expect(tokens[3]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); expect(tokens[4]).toEqual({value: ' ', scopes: ['source.css']}); expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('allows font-feature names to start on a different line', function() { @@ -1731,7 +1725,7 @@ Font name 2 expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css', 'punctuation.definition.keyword.css']}); expect(lines[0][1]).toEqual({value: 'font-feature-values', scopes: ['source.css', 'meta.at-rule.font-features.css', 'keyword.control.at-rule.font-feature-values.css']}); expect(lines[1][0]).toEqual({value: 'Font name 2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); - return expect(lines[2][0]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(lines[2][0]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1750,7 +1744,7 @@ Font name 2 expect(tokens[11]).toEqual({value: '{', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css']}); expect(tokens[12]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[13]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.font-features.css', 'variable.parameter.font-name.css']}); - return expect(tokens[14]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[14]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises at-rules for feature names', function() { @@ -1811,7 +1805,7 @@ Font name 2 expect(lines[5][4]).toEqual({value: 'charvar', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); expect(lines[5][5]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.separator.key-value.css']}); expect(lines[5][7]).toEqual({value: '2', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'meta.property-value.css', 'constant.numeric.css']}); - return expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[5][9]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('matches feature-name rules case-insensitively', function() { @@ -1829,7 +1823,7 @@ Font name 2 expect(lines[2][1]).toEqual({value: 'anNOTatION', scopes: ['source.css', 'meta.at-rule.annotation.css', 'keyword.control.at-rule.annotation.css']}); expect(lines[3][1]).toEqual({value: 'styLISTic', scopes: ['source.css', 'meta.at-rule.stylistic.css', 'keyword.control.at-rule.stylistic.css']}); expect(lines[4][1]).toEqual({value: 'STYLEset', scopes: ['source.css', 'meta.at-rule.styleset.css', 'keyword.control.at-rule.styleset.css']}); - return expect(lines[5][1]).toEqual({value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css']}); + expect(lines[5][1]).toEqual({value: 'CHARacter-VARiant', scopes: ['source.css', 'meta.at-rule.character-variant.css', 'keyword.control.at-rule.character-variant.css']}); }); it('matches comments inside feature-name rules', function() { @@ -1859,10 +1853,10 @@ Font name 2 expect(lines[2][8]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[2][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[2][10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it('highlights escape sequences inside feature-names', function() { + it('highlights escape sequences inside feature-names', function() { const {tokens} = grammar.tokenizeLine('@swash{ s\\000077a\\73hy: 1; }'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'swash', scopes: ['source.css', 'meta.at-rule.swash.css', 'keyword.control.at-rule.swash.css']}); @@ -1870,7 +1864,7 @@ Font name 2 expect(tokens[5]).toEqual({value: '\\000077', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css']}); expect(tokens[6]).toEqual({value: 'a', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); expect(tokens[7]).toEqual({value: '\\73', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css', 'constant.character.escape.codepoint.css']}); - return expect(tokens[8]).toEqual({value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); + expect(tokens[8]).toEqual({value: 'hy', scopes: ['source.css', 'meta.at-rule.swash.css', 'meta.property-list.font-feature.css', 'variable.font-feature.css']}); }); }); @@ -1897,7 +1891,7 @@ Font name 2 expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'page', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); expect(tokens[2]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[3]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[3]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); })); describe('@counter-style', function() { @@ -1938,7 +1932,7 @@ Font name 2 expect(lines[3][4]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(lines[3][6]).toEqual({value: '"', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); expect(lines[3][7]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); - return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('matches injected comments', function() { @@ -1957,7 +1951,7 @@ Font name 2 expect(tokens[12]).toEqual({value: ':', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.separator.key-value.css']}); expect(tokens[14]).toEqual({value: 'fixed', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[17]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[17]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.counter-style.body.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("allows the counter-style's name to start on a different line", function() { @@ -1968,16 +1962,16 @@ winners-list\ ); expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); expect(lines[0][1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); - return expect(lines[1][0]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + expect(lines[1][0]).toEqual({value: 'winners-list', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); }); - return it("highlights escape sequences inside the style's name", function() { + it("highlights escape sequences inside the style's name", function() { const {tokens} = grammar.tokenizeLine('@counter-style A\\01F602z'); expect(tokens[0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css', 'punctuation.definition.keyword.css']}); expect(tokens[1]).toEqual({value: 'counter-style', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'keyword.control.at-rule.counter-style.css']}); expect(tokens[3]).toEqual({value: 'A', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); expect(tokens[4]).toEqual({value: '\\01F602', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css', 'constant.character.escape.codepoint.css']}); - return expect(tokens[5]).toEqual({value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); + expect(tokens[5]).toEqual({value: 'z', scopes: ['source.css', 'meta.at-rule.counter-style.header.css', 'variable.parameter.style-name.css']}); }); }); @@ -2028,7 +2022,7 @@ regexp("https:.*") { expect(lines[4][8]).toEqual({value: 'f00', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.color.rgb-value.hex.css']}); expect(lines[4][9]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[4][11]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); - return expect(lines[5][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css']}); + expect(lines[5][1]).toEqual({value: '}', scopes: ['source.css', 'meta.at-rule.document.body.css', 'punctuation.section.document.end.bracket.curly.css']}); })); describe('@viewport', function() { @@ -2048,7 +2042,7 @@ regexp("https:.*") { expect(tokens[15]).toEqual({value: '800', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(tokens[16]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[17]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[19]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenises them across lines', function() { @@ -2076,10 +2070,10 @@ regexp("https:.*") { expect(lines[4][2]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[4][4]).toEqual({value: '0.9', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[4][5]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[5][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it('tokenises injected comments', function() { + it('tokenises injected comments', function() { const lines = grammar.tokenizeLines(`\ @-ms-viewport/*{*/{/* ==*/orientation: landscape; @@ -2099,11 +2093,11 @@ regexp("https:.*") { expect(lines[1][3]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[1][5]).toEqual({value: 'landscape', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(lines[1][6]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[2][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); - return describe('unknown at-rules', function() { + describe('unknown at-rules', function() { it('correctly parses single-line unknown at-rules closing with semicolons', function() { const lines = grammar.tokenizeLines(`\ @foo; @@ -2124,10 +2118,10 @@ regexp("https:.*") { expect(lines[3][2]).toEqual({value: ' ()', scopes: ['source.css', 'meta.at-rule.header.css']}); expect(lines[4][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); - return expect(lines[4][2]).toEqual({value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css']}); + expect(lines[4][2]).toEqual({value: ' (a)', scopes: ['source.css', 'meta.at-rule.header.css']}); }); - return it('correctly parses single-line unknown at-rules closing with ;', function() { + it('correctly parses single-line unknown at-rules closing with ;', function() { const lines = grammar.tokenizeLines(`\ @foo bar; .foo\ @@ -2136,7 +2130,7 @@ regexp("https:.*") { expect(lines[0][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.at-rule.header.css', 'keyword.control.at-rule.css']}); expect(lines[1][0]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(lines[1][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(lines[1][1]).toEqual({value: 'foo', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); }); }); @@ -2157,7 +2151,7 @@ regexp("https:.*") { expect(lines[2][1]).toEqual({value: 'pAgE', scopes: ['source.css', 'meta.at-rule.page.css', 'keyword.control.at-rule.page.css']}); expect(lines[2][4]).toEqual({value: 'fIRST', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(lines[3][1]).toEqual({value: 'NAMEspace', scopes: ['source.css', 'meta.at-rule.namespace.css', 'keyword.control.at-rule.namespace.css']}); - return expect(lines[4][1]).toEqual({value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css']}); + expect(lines[4][1]).toEqual({value: 'foNT-FacE', scopes: ['source.css', 'meta.at-rule.font-face.css', 'keyword.control.at-rule.font-face.css']}); }); it('ignores case in property names', function() { @@ -2171,7 +2165,7 @@ a{ -MOZ-IMAGE: none; }\ expect(lines[0][3]).toEqual({value: 'COLOR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(lines[1][3]).toEqual({value: 'gRId-tEMPLaTe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(lines[2][3]).toEqual({value: 'bACkgrOUND-iMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); - return expect(lines[3][3]).toEqual({value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); + expect(lines[3][3]).toEqual({value: '-MOZ-IMAGE', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.vendored.property-name.css']}); }); it('ignores case in property keywords', function() { @@ -2193,7 +2187,7 @@ a{ font: HelVETica; }\ expect(lines[4][6]).toEqual({value: 'NONe', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(lines[5][6]).toEqual({value: 'lOWER-lATIN', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); expect(lines[6][6]).toEqual({value: '-WebkIT-foo', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); - return expect(lines[7][6]).toEqual({value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + expect(lines[7][6]).toEqual({value: 'HelVETica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); }); it('ignores case in selectors', function() { @@ -2218,7 +2212,7 @@ I::-mOZ-thing {}\ expect(lines[4][2]).toEqual({value: 'NOT', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(lines[5][0]).toEqual({value: 'I', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(lines[5][2]).toEqual({value: 'BACKDROP', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); - return expect(lines[6][2]).toEqual({value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(lines[6][2]).toEqual({value: '-mOZ-thing', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); it('ignores case in function names', function() { @@ -2240,10 +2234,10 @@ a{ content: cALc(2 + 2)}\ expect(lines[4][6]).toEqual({value: 'CoUNTer', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(lines[5][6]).toEqual({value: 'cuBIC-beZIER', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); expect(lines[6][6]).toEqual({value: 'sTePs', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); - return expect(lines[7][6]).toEqual({value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); + expect(lines[7][6]).toEqual({value: 'cALc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); }); - return it('ignores case in unit names', function() { + it('ignores case in unit names', function() { const lines = grammar.tokenizeLines(`\ a{width: 20EM; } a{width: 20ReM; } @@ -2261,7 +2255,7 @@ a{width: 2gRAd}\ expect(lines[3][6]).toEqual({value: 'S', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.s.css']}); expect(lines[4][5]).toEqual({value: '20', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[4][6]).toEqual({value: 'CM', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.cm.css']}); - return expect(lines[5][6]).toEqual({value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css']}); + expect(lines[5][6]).toEqual({value: 'gRAd', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.grad.css']}); }); }); @@ -2270,7 +2264,7 @@ a{width: 2gRAd}\ const {tokens} = grammar.tokenizeLine('p:first-child'); expect(tokens[0]).toEqual({value: 'p', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[2]).toEqual({value: 'first-child', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); }); it("doesn't tokenise pseudo-classes if followed by a semicolon or closed bracket", function() { @@ -2280,7 +2274,7 @@ a{width: 2gRAd}\ expect(tokens[3]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[5]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); - return expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); describe(':dir()', function() { @@ -2303,10 +2297,10 @@ a:dir(ltr ){ } expect(lines[1][3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[1][4]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); expect(lines[1][5]).toEqual({value: 'rtl', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); - return expect(lines[1][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[1][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('allows :dir() to include comments and newlines', function() { + it('allows :dir() to include comments and newlines', function() { const lines = grammar.tokenizeLines(`\ :DIR(/** ==*/ltr/* @@ -2323,7 +2317,7 @@ a:dir(ltr ){ } expect(lines[1][2]).toEqual({value: 'ltr', scopes: ['source.css', 'meta.selector.css', 'support.constant.text-direction.css']}); expect(lines[1][3]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[2][0]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(lines[2][1]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][1]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2336,15 +2330,15 @@ a:dir(ltr ){ } expect(tokens[3]).toEqual({value: 'zh-Hans-CN', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css']}); expect(tokens[4]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); expect(tokens[5]).toEqual({value: 'es-419', scopes: ['source.css', 'meta.selector.css', 'support.constant.language-range.css']}); - return expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('does not tokenize unquoted language ranges containing asterisks', function() { const {tokens} = grammar.tokenizeLine(':lang(zh-*-CN)'); - return expect(tokens[3]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[3]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css']}); }); - return it('tokenizes language ranges containing asterisks quoted as strings', function() { + it('tokenizes language ranges containing asterisks quoted as strings', function() { const {tokens} = grammar.tokenizeLine(':lang("zh-*-CN",\'*-ab-\')'); expect(tokens[3]).toEqual({value: '"', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[4]).toEqual({value: 'zh-*-CN', scopes: ['source.css', 'meta.selector.css', 'string.quoted.double.css', 'support.constant.language-range.css']}); @@ -2352,7 +2346,7 @@ a:dir(ltr ){ } expect(tokens[6]).toEqual({value: ',', scopes: ['source.css', 'meta.selector.css', 'punctuation.separator.list.comma.css']}); expect(tokens[7]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[8]).toEqual({value: '*-ab-', scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'support.constant.language-range.css']}); - return expect(tokens[9]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); + expect(tokens[9]).toEqual({value: "'", scopes: ['source.css', 'meta.selector.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); }); }); @@ -2369,10 +2363,10 @@ a:dir(ltr ){ } expect(tokens[8]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[10]).toEqual({value: 'div', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); - return expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('tokenises injected comments', function() { + it('tokenises injected comments', function() { const {tokens} = grammar.tokenizeLine('*:not(/*(*/.class-name/*)*/):not(/*b*/) {}'); expect(tokens[2]).toEqual({value: 'not', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); expect(tokens[3]).toEqual({value: '(', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2391,11 +2385,11 @@ a:dir(ltr ){ } expect(tokens[16]).toEqual({value: '/*', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[17]).toEqual({value: 'b', scopes: ['source.css', 'meta.selector.css', 'comment.block.css']}); expect(tokens[18]).toEqual({value: '*/', scopes: ['source.css', 'meta.selector.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); - return describe(':nth-*()', function() { + describe(':nth-*()', function() { it('tokenizes :nth-child()', function() { const tokens = grammar.tokenizeLines(`\ :nth-child(2n+1) @@ -2421,7 +2415,7 @@ a:dir(ltr ){ } expect(tokens[6][3]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[6][4]).toEqual({value: 'odd', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); expect(tokens[7][4]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); - return expect(tokens[7][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[7][5]).toEqual({value: ' ', scopes: ['source.css', 'meta.selector.css']}); }); it('tokenizes :nth-last-child()', function() { @@ -2440,7 +2434,7 @@ a:dir(ltr ){ } expect(tokens[1][4]).toEqual({value: '-2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[2][4]).toEqual({value: '2n', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[2][6]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[3][3]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); + expect(tokens[3][3]).toEqual({value: 'even', scopes: ['source.css', 'meta.selector.css', 'support.constant.parity.css']}); }); it('tokenizes :nth-of-type()', function() { @@ -2456,10 +2450,10 @@ img:nth-of-type(n+1)\ expect(tokens[0][4]).toEqual({value: '+n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[0][5]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[1][4]).toEqual({value: '-n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); - return expect(tokens[2][4]).toEqual({value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[2][4]).toEqual({value: 'n+1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); }); - return it('tokenizes ::nth-last-of-type()', function() { + it('tokenizes ::nth-last-of-type()', function() { const tokens = grammar.tokenizeLines(`\ h1:nth-last-of-type(-1) h1:nth-last-of-type(+2) @@ -2472,7 +2466,7 @@ h1:nth-last-of-type(3)\ expect(tokens[0][4]).toEqual({value: '-1', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); expect(tokens[0][5]).toEqual({value: ')', scopes: ['source.css', 'meta.selector.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[1][4]).toEqual({value: '+2', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); - return expect(tokens[2][4]).toEqual({value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); + expect(tokens[2][4]).toEqual({value: '3', scopes: ['source.css', 'meta.selector.css', 'constant.numeric.css']}); }); }); }); @@ -2489,7 +2483,7 @@ h1:nth-last-of-type(3)\ ({tokens} = grammar.tokenizeLine('q::after')); expect(tokens[0]).toEqual({value: 'q', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(tokens[2]).toEqual({value: 'after', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); it('tokenizes both : and :: notations for vendor-prefixed pseudo-elements', function() { @@ -2499,39 +2493,39 @@ h1:nth-last-of-type(3)\ ({tokens} = grammar.tokenizeLine('::-webkit-input-placeholder')); expect(tokens[0]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - return expect(tokens[1]).toEqual({value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(tokens[1]).toEqual({value: '-webkit-input-placeholder', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); - return it('only tokenizes the :: notation for other pseudo-elements', function() { + it('only tokenizes the :: notation for other pseudo-elements', function() { let {tokens} = grammar.tokenizeLine('::selection'); expect(tokens[0]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); expect(tokens[1]).toEqual({value: 'selection', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); ({tokens} = grammar.tokenizeLine(':selection')); - return expect(tokens[0]).toEqual({value: ':selection', scopes: ['source.css', 'meta.selector.css']}); + expect(tokens[0]).toEqual({value: ':selection', scopes: ['source.css', 'meta.selector.css']}); }); }); - return describe('compound selectors', function() { + describe('compound selectors', function() { it('tokenizes the combination of type selectors followed by class selectors', function() { const {tokens} = grammar.tokenizeLine('very-custom.class'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: '.', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); + expect(tokens[2]).toEqual({value: 'class', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.class.css']}); }); it('tokenizes the combination of type selectors followed by pseudo-classes', function() { const {tokens} = grammar.tokenizeLine('very-custom:hover'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: ':', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); + expect(tokens[2]).toEqual({value: 'hover', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-class.css']}); }); - return it('tokenizes the combination of type selectors followed by pseudo-elements', function() { + it('tokenizes the combination of type selectors followed by pseudo-elements', function() { const {tokens} = grammar.tokenizeLine('very-custom::shadow'); expect(tokens[0]).toEqual({value: 'very-custom', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.custom.css']}); expect(tokens[1]).toEqual({value: '::', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css', 'punctuation.definition.entity.css']}); - return expect(tokens[2]).toEqual({value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); + expect(tokens[2]).toEqual({value: 'shadow', scopes: ['source.css', 'meta.selector.css', 'entity.other.attribute-name.pseudo-element.css']}); }); }); }); @@ -2544,7 +2538,7 @@ h1:nth-last-of-type(3)\ expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes compact inline property lists', function() { @@ -2556,7 +2550,7 @@ h1:nth-last-of-type(3)\ expect(tokens[6]).toEqual({value: 'float', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); expect(tokens[7]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[8]).toEqual({value: 'left', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); - return expect(tokens[9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[9]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes multiple inline property lists', function() { @@ -2578,17 +2572,17 @@ another-one { display : none ; }\ expect(tokens[1][8]).toEqual({value: 'none', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[1][9]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[1][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[1][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[1][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes custom properties', function() { const {tokens} = grammar.tokenizeLine(':root { --white: #FFF; }'); - return expect(tokens[5]).toEqual({value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css']}); + expect(tokens[5]).toEqual({value: '--white', scopes: ['source.css', 'meta.property-list.css', 'variable.css']}); }); it('tokenises commas between property values', function() { const {tokens} = grammar.tokenizeLine('a{ text-shadow: a, b; }'); - return expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[7]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); }); it('tokenises superfluous semicolons', function() { @@ -2601,13 +2595,13 @@ another-one { display : none ; }\ expect(lines[0][i+9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(lines[1][i]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); } - return expect(lines[1][9]).toEqual({value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[1][9]).toEqual({value: 'height', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); }); - return describe('values', function() { + describe('values', function() { it('tokenizes color keywords', function() { const {tokens} = grammar.tokenizeLine('#jon { color: snow; }'); - return expect(tokens[8]).toEqual({value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css']}); + expect(tokens[8]).toEqual({value: 'snow', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-extended-color-name.css']}); }); it('tokenises RGBA values in hex notation', function() { @@ -2628,25 +2622,25 @@ another-one { display : none ; }\ expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); ({tokens} = grammar.tokenizeLine('a{ color: #CAFEBABEF; }')); - return expect(tokens[6]).toEqual({value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[6]).toEqual({value: '#CAFEBABEF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); }); it('tokenizes common font names', function() { const {tokens} = grammar.tokenizeLine('p { font-family: Verdana, Helvetica, sans-serif; }'); expect(tokens[7]).toEqual({value: 'Verdana', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); expect(tokens[10]).toEqual({value: 'Helvetica', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); - return expect(tokens[13]).toEqual({value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); + expect(tokens[13]).toEqual({value: 'sans-serif', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.font-name.css']}); }); it('tokenizes predefined list style types', function() { const {tokens} = grammar.tokenizeLine('ol.myth { list-style-type: cjk-earthly-branch }'); - return expect(tokens[9]).toEqual({value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); + expect(tokens[9]).toEqual({value: 'cjk-earthly-branch', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.list-style-type.css']}); }); it('tokenizes numeric values', function() { const {tokens} = grammar.tokenizeLine('div { font-size: 14px; }'); expect(tokens[7]).toEqual({value: '14', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); - return expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); + expect(tokens[8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); }); it('does not tokenize invalid numeric values', function() { @@ -2654,7 +2648,7 @@ another-one { display : none ; }\ expect(tokens[7]).toEqual({value: 'test14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); ({tokens} = grammar.tokenizeLine('div { font-size: test-14px; }')); - return expect(tokens[7]).toEqual({value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[7]).toEqual({value: 'test-14px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); }); it('tokenizes vendor-prefixed values', function() { @@ -2665,12 +2659,12 @@ another-one { display : none ; }\ expect(tokens[8]).toEqual({value: '-moz-min-content', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); ({tokens} = grammar.tokenizeLine('.edge { display: -ms-grid; }')); - return expect(tokens[8]).toEqual({value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); + expect(tokens[8]).toEqual({value: '-ms-grid', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.vendored.property-value.css']}); }); it('tokenizes custom variables', function() { const {tokens} = grammar.tokenizeLine('div { color: var(--primary-color) }'); - return expect(tokens[9]).toEqual({value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); + expect(tokens[9]).toEqual({value: '--primary-color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); }); it('tokenises numeric values correctly', function() { @@ -2715,7 +2709,7 @@ another-one { display : none ; }\ expect(lines[11][8]).toEqual({value: '+.5E-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(lines[11][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); expect(lines[12][8]).toEqual({value: '-3.4e-2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); - return expect(lines[12][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); + expect(lines[12][9]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); }); describe('functional notation', function() { @@ -2729,10 +2723,10 @@ another-one { display : none ; }\ expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.separator.list.comma.css']}); expect(tokens[11]).toEqual({value: 'inherit', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.constant.property-value.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[13]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it('matches variables', function() { + it('matches variables', function() { const {tokens} = grammar.tokenizeLine('a{content:ATTR(VAR(--name) px, "N/A")}'); expect(tokens[4]).toEqual({value: 'ATTR', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(tokens[5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2745,7 +2739,7 @@ another-one { display : none ; }\ expect(tokens[14]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); expect(tokens[15]).toEqual({value: 'N/A', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css']}); expect(tokens[16]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'string.quoted.double.css', 'punctuation.definition.string.end.css']}); - return expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2775,7 +2769,7 @@ a{ expect(lines[3][9]).toEqual({value: '*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); expect(lines[4][7]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(lines[4][9]).toEqual({value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); - return expect(lines[4][11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(lines[4][11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); }); it('requires whitespace around + and - operators', function() { @@ -2789,7 +2783,7 @@ a{ expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[10]).toEqual({value: '--1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); expect(tokens[19]).toEqual({value: '10', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); - return expect(tokens[20]).toEqual({value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); + expect(tokens[20]).toEqual({value: '-1em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css']}); }); it('does not require whitespace around * and / operators', function() { @@ -2801,10 +2795,10 @@ a{ ({tokens} = grammar.tokenizeLine('a{ width: calc(3px/2); }')); expect(tokens[9]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[10]).toEqual({value: '/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'keyword.operator.arithmetic.css']}); - return expect(tokens[11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); + expect(tokens[11]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css']}); }); - return it('matches variable expansions inside calculations', function() { + it('matches variable expansions inside calculations', function() { const {tokens} = grammar.tokenizeLine('.foo { margin-top: calc(var(--gap) + 1px); }'); expect(tokens[8]).toEqual({value: 'calc', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'support.function.calc.css']}); expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -2817,7 +2811,7 @@ a{ expect(tokens[18]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[19]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.calc.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[20]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[22]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -2872,7 +2866,7 @@ a{ expect(tokens[12]).toEqual({value: '%', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css', 'keyword.other.unit.percentage.css']}); expect(tokens[13]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); expect(tokens[14]).toEqual({value: '.7', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); - return expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('matches variables as colour components', function() { @@ -2882,7 +2876,7 @@ a{ expect(tokens[9]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[10]).toEqual({value: '--red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'variable.argument.css']}); expect(tokens[11]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); + expect(tokens[12]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); }); it('matches comments between colour components', function() { @@ -2901,10 +2895,10 @@ a{ expect(tokens[21]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[22]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); expect(tokens[23]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[24]).toEqual({value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); + expect(tokens[24]).toEqual({value: '0.2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'constant.numeric.css']}); }); - return it('allows colour components to be split across lines', function() { + it('allows colour components to be split across lines', function() { const lines = grammar.tokenizeLines(`\ .frost{ background-color: rgba( @@ -2946,7 +2940,7 @@ a{ expect(lines[6][7]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(lines[6][8]).toEqual({value: ' Transparency ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css']}); expect(lines[6][9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(lines[7][1]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[7][1]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); }); }); @@ -2973,7 +2967,7 @@ a{ expect(tokens[16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); expect(tokens[18]).toEqual({value: 'blue', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); expect(tokens[19]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.separator.list.comma.css']}); - return expect(tokens[21]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); + expect(tokens[21]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.color.w3c-standard-color-name.css']}); }); it('tokenises radial gradients', function() { @@ -3011,7 +3005,7 @@ a{ expect(tokens[36]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.separator.list.comma.css']}); expect(tokens[41]).toEqual({value: '.3', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'constant.numeric.css']}); expect(tokens[42]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[48]).toEqual({value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); + expect(tokens[48]).toEqual({value: 'transparent', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'support.constant.property-value.css']}); }); it('matches gradients that span multiple lines with injected comments', function() { @@ -3046,7 +3040,7 @@ a{ expect(lines[3][27]).toEqual({value: '))))))))}', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); expect(lines[3][28]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(lines[3][29]).toEqual({value: '#', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css', 'punctuation.definition.constant.css']}); - return expect(lines[3][30]).toEqual({value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); + expect(lines[3][30]).toEqual({value: 'E6E6FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'constant.other.color.rgb-value.hex.css']}); }); it('highlights vendored gradient functions', function() { @@ -3082,10 +3076,10 @@ a{ expect(lines[3][5]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[3][10]).toEqual({value: ' For old Opera (11.1 to 12.0) ', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'comment.block.css']}); expect(lines[3][13]).toEqual({value: 'hsl', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'support.function.misc.css']}); - return expect(lines[3][14]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); + expect(lines[3][14]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.css', 'meta.function.color.css', 'punctuation.section.function.begin.bracket.round.css']}); }); - return it('highlights antique Webkit syntax as deprecated', function() { + it('highlights antique Webkit syntax as deprecated', function() { const lines = grammar.tokenizeLines(`\ .grad { background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, @@ -3155,7 +3149,7 @@ a{ expect(lines[9][8]).toEqual({value: '150', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'constant.numeric.css']}); expect(lines[9][54]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.gradient.invalid.deprecated.gradient.css', 'punctuation.section.function.end.bracket.round.css']}); expect(lines[9][55]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[10][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[10][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3194,7 +3188,7 @@ a{ expect(lines[2][16]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.separator.list.comma.css']}); expect(lines[2][18]).toEqual({value: '1', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css']}); expect(lines[2][19]).toEqual({value: 'em', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'constant.numeric.css', 'keyword.other.unit.em.css']}); - return expect(lines[2][20]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[2][20]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.shape.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('tokenises OpenType feature functions', function() { @@ -3241,10 +3235,10 @@ a{ expect(lines[7][9]).toEqual({value: 'annotation', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'support.function.misc.css']}); expect(lines[7][10]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(lines[7][11]).toEqual({value: 'ident2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'variable.parameter.misc.css']}); - return expect(lines[7][12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(lines[7][12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('tokenises image-set()', function() { + it('tokenises image-set()', function() { const lines = grammar.tokenizeLines(`\ a{ background-image: image-set( "foo.png" 1x, @@ -3276,7 +3270,7 @@ a{ expect(lines[3][6]).toEqual({value: 'dpi', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'constant.numeric.css', 'keyword.other.unit.dpi.css']}); expect(lines[3][8]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.misc.css', 'punctuation.section.function.end.bracket.round.css']}); expect(lines[3][9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3299,10 +3293,10 @@ a{ expect(tokens[19]).toEqual({value: '0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'constant.numeric.css']}); expect(tokens[20]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[21]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[22]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[22]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('highlights the "start" and "end" keywords', function() { + it('highlights the "start" and "end" keywords', function() { const {tokens} = grammar.tokenizeLine('a{ before: steps(0, start); after: steps(1, end); }'); expect(tokens[6]).toEqual({value: 'steps', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.function.timing-function.css']}); expect(tokens[7]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -3310,7 +3304,7 @@ a{ expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.separator.list.comma.css']}); expect(tokens[11]).toEqual({value: 'start', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[23]).toEqual({value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); + expect(tokens[23]).toEqual({value: 'end', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.timing-function.css', 'support.constant.step-direction.css']}); }); }); @@ -3331,7 +3325,7 @@ a{ expect(tokens[5]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); expect(tokens[6]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); expect(tokens[8]).toEqual({value: '--name', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); - return expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[10]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); }); it('allows injected comments', function() { @@ -3342,10 +3336,10 @@ a{ expect(tokens[10]).toEqual({value: '=', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css']}); expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[13]).toEqual({value: '--something', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'variable.argument.css']}); - return expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); + expect(tokens[15]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); }); - return it('tokenises fallback values', function() { + it('tokenises fallback values', function() { const {tokens} = grammar.tokenizeLine('.bar{ width: var(--page-width, /*;;;);*/ 2); }'); expect(tokens[7]).toEqual({value: 'var', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'support.function.misc.css']}); expect(tokens[8]).toEqual({value: '(', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.begin.bracket.round.css']}); @@ -3356,11 +3350,11 @@ a{ expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[16]).toEqual({value: '2', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'constant.numeric.css']}); expect(tokens[17]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'meta.function.variable.css', 'punctuation.section.function.end.bracket.round.css']}); - return expect(tokens[18]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); + expect(tokens[18]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); }); }); - return it('does not tokenise functions with whitespace between name and parameters', function() { + it('does not tokenise functions with whitespace between name and parameters', function() { let {tokens} = grammar.tokenizeLine('a{ p: attr (title); }'); expect(tokens[0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[1]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); @@ -3415,14 +3409,14 @@ a{ expect(tokens[11]).toEqual({value: '221', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css']}); expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[13]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[15]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[15]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); - return describe('Unicode ranges', function() { + describe('Unicode ranges', function() { it('tokenises single codepoints', function() { const {tokens} = grammar.tokenizeLine('a{ a: U+A5 }'); - return expect(tokens[6]).toEqual({value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[6]).toEqual({value: 'U+A5', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); it('tokenises codepoint ranges', function() { @@ -3434,10 +3428,10 @@ a{ ({tokens} = grammar.tokenizeLine('a{ unicode-range: u+0-7F }')); expect(tokens[6]).toEqual({value: 'u+0', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); - return expect(tokens[8]).toEqual({value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[8]).toEqual({value: '7F', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); - return it('tokenises wildcard ranges', function() { + it('tokenises wildcard ranges', function() { let {tokens} = grammar.tokenizeLine('a{ unicode-range: U+4?? }'); expect(tokens[6]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); @@ -3446,7 +3440,7 @@ a{ expect(tokens[7]).toEqual({value: '-', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css', 'punctuation.separator.dash.unicode-range.css']}); expect(tokens[8]).toEqual({value: '00FF', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); expect(tokens[9]).toEqual({value: ',', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.separator.list.comma.css']}); - return expect(tokens[11]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); + expect(tokens[11]).toEqual({value: 'U+4??', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.other.unicode-range.css']}); }); }); }); @@ -3464,7 +3458,7 @@ a{ expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); - return expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'constant.character.escape.codepoint.css']}); }); it('tokenizes escape sequences in double-quoted strings', function() { @@ -3478,7 +3472,7 @@ a{ expect(tokens[5]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); expect(tokens[7]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); - return expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css']}); + expect(tokens[8]).toEqual({value: '\\c0ffee', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'constant.character.escape.codepoint.css']}); }); it('tokenises escape sequences in selectors', function() { @@ -3496,7 +3490,7 @@ a{ expect(tokens[4]).toEqual({value: '\\@', scopes: ['source.css', 'constant.character.escape.css']}); expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.selector.css']}); expect(tokens[6]).toEqual({value: ' ', scopes: ['source.css']}); - return expect(tokens[7]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); + expect(tokens[7]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); }); it('tokenises escape sequences in property lists', function() { @@ -3506,14 +3500,14 @@ a{ expect(tokens[6]).toEqual({value: '\\64', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); expect(tokens[7]).toEqual({value: '\\74', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); expect(tokens[8]).toEqual({value: '\\68', scopes: ['source.css', 'meta.property-list.css', 'constant.character.escape.codepoint.css']}); - return expect(tokens[9]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); + expect(tokens[9]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); }); - return it('tokenises escape sequences in property values', function() { + it('tokenises escape sequences in property values', function() { const {tokens} = grammar.tokenizeLine('a { content: \\1F764; }'); expect(tokens[7]).toEqual({value: '\\1F764', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.character.escape.codepoint.css']}); expect(tokens[8]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3527,7 +3521,7 @@ a{ ({tokens} = grammar.tokenizeLine('a{ content: "aaaa')); expect(tokens[4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(tokens[6]).toEqual({value: '"', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'punctuation.definition.string.begin.css']}); - return expect(tokens[7]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); + expect(tokens[7]).toEqual({value: 'aaaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.double.css', 'invalid.illegal.unclosed.string.css']}); }); it("knows when a string is line-wrapped", function() { @@ -3561,7 +3555,7 @@ aaa'; color: red; expect(lines[2][0]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css']}); expect(lines[2][1]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.end.css']}); expect(lines[2][2]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[2][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); + expect(lines[2][4]).toEqual({value: 'color', scopes: ['source.css', 'meta.property-list.css', 'meta.property-name.css', 'support.type.property-name.css']}); }); it('highlights escape sequences inside invalid strings', function() { @@ -3575,10 +3569,10 @@ aaa'; color: red; expect(tokens[6]).toEqual({value: "'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'punctuation.definition.string.begin.css']}); expect(tokens[7]).toEqual({value: 'aaa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); expect(tokens[8]).toEqual({value: "\\'", scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css', 'constant.character.escape.css']}); - return expect(tokens[9]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); + expect(tokens[9]).toEqual({value: 'aa', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'string.quoted.single.css', 'invalid.illegal.unclosed.string.css']}); }); - return it('highlights unclosed lines in line-wrapped strings', function() { + it('highlights unclosed lines in line-wrapped strings', function() { const lines = grammar.tokenizeLines(`\ a{ content: "aaa\\"aa\\ @@ -3599,7 +3593,7 @@ aaaa; color: red; expect(lines[3][4]).toEqual({value: ':', scopes: ['source.css', 'meta.property-list.css', 'punctuation.separator.key-value.css']}); expect(lines[3][6]).toEqual({value: 'red', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.color.w3c-standard-color-name.css']}); expect(lines[3][7]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); - return expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[4][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3643,7 +3637,7 @@ aaaa; color: red; expect(tokens[12]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[13]).toEqual({value: ' url(";"); ', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css']}); expect(tokens[14]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.import.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); + expect(tokens[15]).toEqual({value: ';', scopes: ['source.css', 'meta.at-rule.import.css', 'punctuation.terminator.rule.css']}); }); it('tokenises comments inside @font-face statements', function() { @@ -3654,7 +3648,7 @@ aaaa; color: red; expect(tokens[3]).toEqual({value: '"{;}"', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css']}); expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.font-face.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[5]).toEqual({value: '{', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.begin.bracket.curly.css']}); - return expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[6]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it('tokenizes comments before media queries', function() { @@ -3664,7 +3658,7 @@ aaaa; color: red; expect(tokens[1]).toEqual({value: ' comment ', scopes: ['source.css', 'comment.block.css']}); expect(tokens[2]).toEqual({value: '*/', scopes: ['source.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); expect(tokens[4]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css', 'punctuation.definition.keyword.css']}); - return expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); + expect(tokens[5]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); }); it('tokenizes comments after media queries', function() { @@ -3674,7 +3668,7 @@ aaaa; color: red; expect(tokens[1]).toEqual({value: 'media', scopes: ['source.css', 'meta.at-rule.media.header.css', 'keyword.control.at-rule.media.css']}); expect(tokens[2]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[3]).toEqual({value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); - return expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); + expect(tokens[4]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); }); it('tokenizes comments inside query lists', function() { @@ -3690,7 +3684,7 @@ aaaa; color: red; expect(tokens[9]).toEqual({value: '/*', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[10]).toEqual({value: ' comment ', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css']}); expect(tokens[11]).toEqual({value: '*/', scopes: ['source.css', 'meta.at-rule.media.header.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); + expect(tokens[12]).toEqual({value: ')', scopes: ['source.css', 'meta.at-rule.media.header.css', 'punctuation.definition.parameters.end.bracket.round.css']}); }); it('tokenizes inline comments', function() { @@ -3706,10 +3700,10 @@ aaaa; color: red; expect(tokens[7]).toEqual({value: '/*', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.begin.css']}); expect(tokens[8]).toEqual({value: 'padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); expect(tokens[9]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[10]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it('tokenizes multi-line comments', function() { + it('tokenizes multi-line comments', function() { const lines = grammar.tokenizeLines(`\ section { border:4px /*1px; @@ -3725,7 +3719,7 @@ aaaa; color: red; expect(lines[2][0]).toEqual({value: ' padding:1px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css']}); expect(lines[2][1]).toEqual({value: '*/', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'comment.block.css', 'punctuation.definition.comment.end.css']}); - return expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(lines[3][0]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); @@ -3738,7 +3732,7 @@ animation-name: line-scale; ` ); expect(tokens[1][4]).toEqual({value: 'orphan-black', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); - return expect(tokens[2][4]).toEqual({value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); + expect(tokens[2][4]).toEqual({value: 'line-scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css']}); })); describe('Transforms', () => it('tokenizes transform functions', function() { @@ -3760,7 +3754,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); expect(tokens[1][23]).toEqual({value: ')', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'punctuation.section.function.end.bracket.round.css']}); expect(tokens[2][4]).toEqual({value: 'rotate', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); expect(tokens[2][10]).toEqual({value: 'translateX', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); - return expect(tokens[2][16]).toEqual({value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); + expect(tokens[2][16]).toEqual({value: 'scale', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.function.transform.css']}); })); describe("performance regressions", function() { @@ -3768,10 +3762,10 @@ transform: rotate(90deg) translateX(100px) scale(1.5); grammar = atom.grammars.grammarForScopeName('source.css'); const start = Date.now(); grammar.tokenizeLine(' @@ -3779,7 +3773,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); \ ` ); - return expect(Date.now() - start).toBeLessThan(5000); + expect(Date.now() - start).toBeLessThan(5000); }); }); @@ -3829,7 +3823,7 @@ transform: rotate(90deg) translateX(100px) scale(1.5); })(); }); - return it("recognises Vim modelines", function() { + it("recognises Vim modelines", function() { let line; const valid = `\ vim: se filetype=css: @@ -3883,7 +3877,7 @@ _vi: se filetype=CSS: }); }); - return describe("Missing supported properties regressions", function() { + describe("Missing supported properties regressions", function() { it("recognises place-items property as supported", function() { const tokens = grammar.tokenizeLines('a { place-items: center center; }'); expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); @@ -3898,7 +3892,7 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("recognises place-self property as supported", function() { @@ -3915,7 +3909,7 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); it("recognises place-content property as supported", function() { @@ -3932,10 +3926,10 @@ _vi: se filetype=CSS: expect(tokens[0][9]).toEqual({value: 'center', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'support.constant.property-value.css']}); expect(tokens[0][10]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][11]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - return expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[0][12]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); - return it("recognises row-gap property as supported", function() { + it("recognises row-gap property as supported", function() { const tokens = grammar.tokenizeLines('a { row-gap: 5px; }'); expect(tokens[0][0]).toEqual({value: 'a', scopes: ['source.css', 'meta.selector.css', 'entity.name.tag.css']}); expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.css']}); @@ -3948,7 +3942,7 @@ _vi: se filetype=CSS: expect(tokens[0][8]).toEqual({value: 'px', scopes: ['source.css', 'meta.property-list.css', 'meta.property-value.css', 'constant.numeric.css', 'keyword.other.unit.px.css']}); expect(tokens[0][9]).toEqual({value: ';', scopes: ['source.css', 'meta.property-list.css', 'punctuation.terminator.rule.css']}); expect(tokens[0][10]).toEqual({value: ' ', scopes: ['source.css', 'meta.property-list.css']}); - return expect(tokens[0][11]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); + expect(tokens[0][11]).toEqual({value: '}', scopes: ['source.css', 'meta.property-list.css', 'punctuation.section.property-list.end.bracket.curly.css']}); }); }); }); From a03ab9738bf7b6967b280f35686e0d8078143724 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sun, 9 Jul 2023 23:29:23 -0700 Subject: [PATCH 17/18] Add lost tabs to css specs --- packages/language-css/spec/css-spec.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/language-css/spec/css-spec.js b/packages/language-css/spec/css-spec.js index 20f1373cf0..614e2d5940 100644 --- a/packages/language-css/spec/css-spec.js +++ b/packages/language-css/spec/css-spec.js @@ -1978,11 +1978,11 @@ winners-list\ describe('@document', () => it('correctly tokenises @document rules', function() { const lines = grammar.tokenizeLines(`\ @document url(http://www.w3.org/), -url-prefix(http://www.w3.org/Style/), /* Comment */ -domain(/**/mozilla.org), -regexp("https:.*") { - body{ color: #f00; } -}\ + url-prefix(http://www.w3.org/Style/), /* Comment */ + domain(/**/mozilla.org), + regexp("https:.*") { + body{ color: #f00; } + }\ ` ); expect(lines[0][0]).toEqual({value: '@', scopes: ['source.css', 'meta.at-rule.document.header.css', 'keyword.control.at-rule.document.css', 'punctuation.definition.keyword.css']}); @@ -3726,8 +3726,8 @@ aaaa; color: red; describe('Animations', () => it('does not confuse animation names with predefined keywords', function() { const tokens = grammar.tokenizeLines(`\ .animated { -animation-name: orphan-black; -animation-name: line-scale; + animation-name: orphan-black; + animation-name: line-scale; }\ ` ); @@ -3738,8 +3738,8 @@ animation-name: line-scale; describe('Transforms', () => it('tokenizes transform functions', function() { const tokens = grammar.tokenizeLines(`\ .transformed { -transform: matrix(0, 1.5, -1.5, 0, 0, 100px); -transform: rotate(90deg) translateX(100px) scale(1.5); + transform: matrix(0, 1.5, -1.5, 0, 0, 100px); + transform: rotate(90deg) translateX(100px) scale(1.5); }\ ` ); From 77199b47263ac5db3c7036c46ea3a57da06a5052 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sun, 9 Jul 2023 23:29:32 -0700 Subject: [PATCH 18/18] Apply lost tabs to c specs --- packages/language-c/spec/c-spec.js | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/language-c/spec/c-spec.js b/packages/language-c/spec/c-spec.js index 066edf31d3..da1220094a 100644 --- a/packages/language-c/spec/c-spec.js +++ b/packages/language-c/spec/c-spec.js @@ -684,48 +684,48 @@ int something() { it("indents allman-style curly braces", () => expectPreservedIndentation(`\ if (a) { -for (;;) -{ - do + for (;;) { - while (b) + do { - c(); + while (b) + { + c(); + } } + while (d) } - while (d) -} }\ ` )); it("indents non-allman-style curly braces", () => expectPreservedIndentation(`\ if (a) { -for (;;) { - do { - while (b) { - c(); - } - } while (d) -} + for (;;) { + do { + while (b) { + c(); + } + } while (d) + } }\ ` )); it("indents function arguments", () => expectPreservedIndentation(`\ a( -b, -c( - d -) + b, + c( + d + ) );\ ` )); it("indents array and struct literals", () => expectPreservedIndentation(`\ some_t a[3] = { -{ .b = c }, -{ .b = c, .d = {1, 2} }, + { .b = c }, + { .b = c, .d = {1, 2} }, };\ ` ));