From 84365cfba10869812db84124fb6489f9b72e867e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Sun, 11 Dec 2016 16:51:11 +0100 Subject: [PATCH] Generate classic-style tokens for css and add tests --- src/css.ts | 354 ++++++++++++++++++----------------- test/all.js | 1 + test/css.test.ts | 476 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 657 insertions(+), 174 deletions(-) create mode 100644 test/css.test.ts diff --git a/src/css.ts b/src/css.ts index 4e2a704a..0ec31b2a 100644 --- a/src/css.ts +++ b/src/css.ts @@ -9,182 +9,188 @@ import LanguageConfiguration = monaco.languages.LanguageConfiguration; import IMonarchLanguage = monaco.languages.IMonarchLanguage; export var conf:LanguageConfiguration = { - wordPattern: /(#?-?\d*\.\d\w*%?)|((::|[@#.!:])?[\w-?]+%?)|::|[@#.!:]/g, - - comments: { - blockComment: ['/*', '*/'] - }, - - brackets: [ - ['{', '}'], - ['[', ']'], - ['(', ')'] - ], - - autoClosingPairs: [ - { open: '{', close: '}' }, - { open: '[', close: ']' }, - { open: '(', close: ')' }, - { open: '"', close: '"', notIn: ['string'] }, - { open: '\'', close: '\'', notIn: ['string'] } - ] + wordPattern: /(#?-?\d*\.\d\w*%?)|((::|[@#.!:])?[\w-?]+%?)|::|[@#.!:]/g, + + comments: { + blockComment: ['/*', '*/'] + }, + + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"', notIn: ['string'] }, + { open: '\'', close: '\'', notIn: ['string'] } + ] }; -const TOKEN_SELECTOR = 'entity.name.selector'; -const TOKEN_SELECTOR_TAG = 'entity.name.tag'; -const TOKEN_PROPERTY = 'support.type.property-name'; -const TOKEN_VALUE = 'support.property-value'; -const TOKEN_AT_KEYWORD = 'keyword.control.at-rule'; +const TOKEN_SELECTOR = 'tag'; +const TOKEN_SELECTOR_TAG = 'tag'; +const TOKEN_PROPERTY = 'attribute.name'; +const TOKEN_VALUE = 'attribute.value'; +const TOKEN_AT_KEYWORD = 'keyword'; export var language = { - defaultToken: '', - tokenPostfix: '.css', - - ws: '[ \t\n\r\f]*', // whitespaces (referenced in several rules) - identifier: '-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*', - - brackets: [ - { open: '{', close: '}', token: 'punctuation.curly' }, - { open: '[', close: ']', token: 'punctuation.bracket' }, - { open: '(', close: ')', token: 'punctuation.parenthesis' }, - { open: '<', close: '>', token: 'punctuation.angle' } - ], - - tokenizer: { - root: [ - { include: '@selector' }, - ], - - selector: [ - { include: '@comments' }, - { include: '@import' }, - ['[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)', { token: TOKEN_AT_KEYWORD, next: '@keyframedeclaration' }], - ['[@](page|content|font-face|-moz-document)', { token: TOKEN_AT_KEYWORD }], - ['[@](charset|namespace)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }], - ['url(\\-prefix)?\\(', { token: 'support.function.name', bracket: '@open', next: '@urldeclaration' }], - { include: '@selectorname' }, - ['[\\*]', TOKEN_SELECTOR_TAG], // selector symbols - ['[>\\+,]', 'punctuation'], // selector operators - ['\\[', { token: 'punctuation.bracket', bracket: '@open', next: '@selectorattribute' }], - ['{', { token: 'punctuation.curly', bracket: '@open', next: '@selectorbody' }] - ], - - selectorbody: [ - ['[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))', TOKEN_PROPERTY, '@rulevalue'], // rule definition: to distinguish from a nested selector check for whitespace, number or a semicolon - ['}', { token: 'punctuation.curly', bracket: '@close', next: '@pop' }] - ], - - selectorname: [ - ['(\\.|#(?=[^{])|%|(@identifier)|:)+', TOKEN_SELECTOR], // selector (.foo, div, ...) - ], - - selectorattribute: [ - { include: '@term' }, - [']', { token: 'punctuation.bracket', bracket: '@close', next: '@pop' }], - ], - - term: [ - { include: '@comments' }, - ['url(\\-prefix)?\\(', { token: 'support.function.name', bracket: '@open', next: '@urldeclaration' }], - { include: '@functioninvocation' }, - { include: '@numbers' }, - { include: '@name' }, - ['([<>=\\+\\-\\*\\/\\^\\|\\~,])', 'keyword.operator'], - [',', 'punctuation'] - ], - - rulevalue: [ - { include: '@term' }, - ['!important', 'literal'], - [';', 'punctuation', '@pop'], - ['(?=})', { token: '', next: '@pop' }] // missing semicolon - ], - - warndebug: [ - ['[@](warn|debug)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }] - ], - - import: [ - ['[@](import)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }] - ], - - urldeclaration: [ - { include: '@strings' }, - ['[^)\r\n]+', 'string'], - ['\\)', { token: 'support.function.name', bracket: '@close', next: '@pop' }] - ], - - parenthizedterm: [ - { include: '@term' }, - ['\\)', { token: 'punctuation.parenthesis', bracket: '@close', next: '@pop' }] - ], - - declarationbody: [ - { include: '@term' }, - [';', 'punctuation', '@pop'], - ['(?=})', { token: '', next: '@pop' }] // missing semicolon - ], - - comments: [ - ['\\/\\*', 'comment', '@comment'], - ['\\/\\/+.*', 'comment'] - ], - - comment: [ - ['\\*\\/', 'comment', '@pop'], - ['.', 'comment'] - ], - - name: [ - ['@identifier', TOKEN_VALUE] - ], - - numbers: [ - ['(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', { token: 'constant.numeric', next: '@units' }], - ['#[0-9a-fA-F_]+(?!\\w)', 'constant.rgb-value'] - ], - - units: [ - ['(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?', 'constant.numeric', '@pop'] - ], - - keyframedeclaration: [ - ['@identifier', 'support.function.name'], - ['{', { token: 'punctuation.curly', bracket: '@open', switchTo: '@keyframebody' }], - ], - - keyframebody: [ - { include: '@term' }, - ['{', { token: 'punctuation.curly', bracket: '@open', next: '@selectorbody' }], - ['}', { token: 'punctuation.curly', bracket: '@close', next: '@pop' }], - ], - - functioninvocation: [ - ['@identifier\\(', { token: 'support.function.name', bracket: '@open', next: '@functionarguments' }], - ], - - functionarguments: [ - ['\\$@identifier@ws:', TOKEN_PROPERTY], - ['[,]', 'punctuation'], - { include: '@term' }, - ['\\)', { token: 'support.function.name', bracket: '@close', next: '@pop' }], - ], - - strings: [ - ['~?"', { token: 'string.punctuation', bracket: '@open', next: '@stringenddoublequote' }], - ['~?\'', { token: 'string.punctuation', bracket: '@open', next: '@stringendquote' }] - ], - - stringenddoublequote: [ - ['\\\\.', 'string'], - ['"', { token: 'string.punctuation', next: '@pop', bracket: '@close' }], - ['.', 'string'] - ], - - stringendquote: [ - ['\\\\.', 'string'], - ['\'', { token: 'string.punctuation', next: '@pop', bracket: '@close' }], - ['.', 'string'] - ] - } + defaultToken: '', + tokenPostfix: '.css', + + ws: '[ \t\n\r\f]*', // whitespaces (referenced in several rules) + identifier: '-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*', + + brackets: [ + { open: '{', close: '}', token: 'delimiter.bracket' }, + { open: '[', close: ']', token: 'delimiter.bracket' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + tokenizer: { + root: [ + { include: '@selector' }, + ], + + selector: [ + { include: '@comments' }, + { include: '@import' }, + { include: '@strings' }, + ['[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)', { token: TOKEN_AT_KEYWORD, next: '@keyframedeclaration' }], + ['[@](page|content|font-face|-moz-document)', { token: TOKEN_AT_KEYWORD }], + ['[@](charset|namespace)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }], + ['(url-prefix)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] ], + ['(url)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] ], + { include: '@selectorname' }, + ['[\\*]', TOKEN_SELECTOR_TAG], // selector symbols + ['[>\\+,]', 'delimiter'], // selector operators + ['\\[', { token: 'delimiter.bracket', next: '@selectorattribute' }], + ['{', { token: 'delimiter.bracket', next: '@selectorbody' }] + ], + + selectorbody: [ + { include: '@comments' }, + ['[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))', TOKEN_PROPERTY, '@rulevalue'], // rule definition: to distinguish from a nested selector check for whitespace, number or a semicolon + ['}', { token: 'delimiter.bracket', next: '@pop' }] + ], + + selectorname: [ + ['(\\.|#(?=[^{])|%|(@identifier)|:)+', TOKEN_SELECTOR], // selector (.foo, div, ...) + ], + + selectorattribute: [ + { include: '@term' }, + [']', { token: 'delimiter.bracket', next: '@pop' }], + ], + + term: [ + { include: '@comments' }, + ['(url-prefix)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] ], + ['(url)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] ], + { include: '@functioninvocation' }, + { include: '@numbers' }, + { include: '@name' }, + ['([<>=\\+\\-\\*\\/\\^\\|\\~,])', 'delimiter'], + [',', 'delimiter'] + ], + + rulevalue: [ + { include: '@comments' }, + { include: '@strings' }, + { include: '@term' }, + ['!important', 'keyword'], + [';', 'delimiter', '@pop'], + ['(?=})', { token: '', next: '@pop' }] // missing semicolon + ], + + warndebug: [ + ['[@](warn|debug)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }] + ], + + import: [ + ['[@](import)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }] + ], + + urldeclaration: [ + { include: '@strings' }, + ['[^)\r\n]+', 'string'], + ['\\)', { token: 'delimiter.parenthesis', next: '@pop' }] + ], + + parenthizedterm: [ + { include: '@term' }, + ['\\)', { token: 'delimiter.parenthesis', next: '@pop' }] + ], + + declarationbody: [ + { include: '@term' }, + [';', 'delimiter', '@pop'], + ['(?=})', { token: '', next: '@pop' }] // missing semicolon + ], + + comments: [ + ['\\/\\*', 'comment', '@comment'], + ['\\/\\/+.*', 'comment'] + ], + + comment: [ + ['\\*\\/', 'comment', '@pop'], + ['.', 'comment'] + ], + + name: [ + ['@identifier', TOKEN_VALUE] + ], + + numbers: [ + ['-?(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', { token: 'attribute.value.number', next: '@units' }], + ['#[0-9a-fA-F_]+(?!\\w)', 'attribute.value.hex'] + ], + + units: [ + ['(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?', 'attribute.value.unit', '@pop'] + ], + + keyframedeclaration: [ + ['@identifier', 'attribute.value'], + ['{', { token: 'delimiter.bracket', switchTo: '@keyframebody' }], + ], + + keyframebody: [ + { include: '@term' }, + ['{', { token: 'delimiter.bracket', next: '@selectorbody' }], + ['}', { token: 'delimiter.bracket', next: '@pop' }], + ], + + functioninvocation: [ + ['@identifier\\(', { token: 'attribute.value', next: '@functionarguments' }], + ], + + functionarguments: [ + ['\\$@identifier@ws:', TOKEN_PROPERTY], + ['[,]', 'delimiter'], + { include: '@term' }, + ['\\)', { token: 'attribute.value', next: '@pop' }], + ], + + strings: [ + ['~?"', { token: 'string', next: '@stringenddoublequote' }], + ['~?\'', { token: 'string', next: '@stringendquote' }] + ], + + stringenddoublequote: [ + ['\\\\.', 'string'], + ['"', { token: 'string', next: '@pop', bracket: '@close' }], + ['.', 'string'] + ], + + stringendquote: [ + ['\\\\.', 'string'], + ['\'', { token: 'string', next: '@pop', bracket: '@close' }], + ['.', 'string'] + ] + } }; \ No newline at end of file diff --git a/test/all.js b/test/all.js index 264734ed..a570434d 100644 --- a/test/all.js +++ b/test/all.js @@ -24,6 +24,7 @@ requirejs([ ], function() { requirejs([ 'out/test/bat.test', + 'out/test/css.test', 'out/test/coffee.test', 'out/test/cpp.test', 'out/test/csharp.test', diff --git a/test/css.test.ts b/test/css.test.ts new file mode 100644 index 00000000..0b77e2af --- /dev/null +++ b/test/css.test.ts @@ -0,0 +1,476 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {testTokenization} from './testRunner'; + +testTokenization('css', [ + // Skip whitespace + [{ + line: ' body', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'tag.css' } + ]}], + + // CSS rule + // body { + // margin: 0; + // padding: 3em 6em; + // font-family: tahoma, arial, sans-serif; + // text-decoration: none !important; + // color: #000 + // } + [{ + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.bracket.css' } + ]}, { + line: ' margin: 0;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'attribute.value.number.css' }, + { startIndex: 11, type: 'delimiter.css' } + ]}, { + line: ' padding: 3em 6em;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'attribute.value.number.css' }, + { startIndex: 12, type: 'attribute.value.unit.css' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'attribute.value.number.css' }, + { startIndex: 16, type: 'attribute.value.unit.css' }, + { startIndex: 18, type: 'delimiter.css' } + ]}, { + line: ' font-family: tahoma, arial, sans-serif;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'attribute.value.css' }, + { startIndex: 21, type: 'delimiter.css' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'attribute.value.css' }, + { startIndex: 28, type: 'delimiter.css' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'attribute.value.css' }, + { startIndex: 40, type: 'delimiter.css' } + ]}, { + line: ' text-decoration: none !important;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'attribute.value.css' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'keyword.css' }, + { startIndex: 34, type: 'delimiter.css' } + ]}, { + line: ' color: #000', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'attribute.value.hex.css' } + ]}, { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' } + ]}], + + // CSS units and numbers + [{ + line: '* { padding: 3em -9pt -0.5px; }', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'attribute.name.css' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'attribute.value.number.css' }, + { startIndex: 14, type: 'attribute.value.unit.css' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'attribute.value.number.css' }, + { startIndex: 19, type: 'attribute.value.unit.css' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'attribute.value.number.css' }, + { startIndex: 26, type: 'attribute.value.unit.css' }, + { startIndex: 28, type: 'delimiter.css' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'delimiter.bracket.css' } + ]}], + + // CSS unfinished unit and numbers + [{ + line: '* { padding: -', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'attribute.name.css' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'delimiter.css' } + ]}], + + // CSS single line comment + // h1 /*comment*/ p { + [{ + line: 'h1 /*comment*/ p {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'comment.css' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'tag.css' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.bracket.css' } + ]}], + + // CSS multi line comment + // h1 /*com + // ment*/ p { + [{ + line: 'h1 /*com', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'comment.css' } + ]}, { + line: 'ment*/ p', + tokens: [ + { startIndex: 0, type: 'comment.css' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'tag.css' } + ]}], + + // CSS ID rule + [{ + line: '#myID {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.bracket.css' } + ]}], + + // CSS Class rules + [{ + line: '.myID {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.bracket.css' } + ]}], + + // CSS @import etc + [{ + line: '@import url(\"something.css\");', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.value.css' }, + { startIndex: 11, type: 'delimiter.parenthesis.css' }, + { startIndex: 12, type: 'string.css' }, + { startIndex: 27, type: 'delimiter.parenthesis.css' }, + { startIndex: 28, type: 'delimiter.css' } + ]}], + + // CSS multi-line string with an escaped newline + // body { + // content: 'con\ + // tent'; + [{ + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.bracket.css' }, + ]}, { + line: ' content: \"con\\', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.css' } + ]}, { + line: 'tent\";', + tokens: [ + { startIndex: 0, type: 'string.css' }, + { startIndex: 5, type: 'delimiter.css' } + ]}], + + // CSS empty string value + // body { + // content: ''; + [{ + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.bracket.css' }, + ]}, { + line: ' content: \"\";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.css' }, + { startIndex: 13, type: 'delimiter.css' } + ]}], + + // CSS font face + // @font-face { + // font-family: 'Opificio'; + // } + [{ + line: '@font-face {', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.bracket.css' } + ]}, { + line: ' font-family: "Opificio";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'string.css' }, + { startIndex: 25, type: 'delimiter.css' } + ]}], + + // CSS string with escaped quotes + // 's\"tr' + [{ + line: '\"s\\\"tr\" ', + tokens: [ + { startIndex: 0, type: 'string.css' }, + { startIndex: 7, type: '' } + ]}], + + // CSS key frame animation syntax + //@-webkit-keyframes infinite-spinning { + // from { + // -webkit-transform: rotate(0deg); + // } + // to { + // -webkit-transform: rotate(360deg); + // } + //} + [{ + line: '@-webkit-keyframes infinite-spinning {', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'attribute.value.css' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'delimiter.bracket.css' } + ]}, { + line: ' from {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.value.css' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.bracket.css' } + ]}, { + line: ' -webkit-transform: rotate(0deg);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'attribute.value.css' }, + { startIndex: 28, type: 'attribute.value.number.css' }, + { startIndex: 29, type: 'attribute.value.unit.css' }, + { startIndex: 32, type: 'attribute.value.css' }, + { startIndex: 33, type: 'delimiter.css' } + ]}, { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' } + ]}, { + line: ' to {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.value.css' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.bracket.css' } + ]}, { + line: ' -webkit-transform: rotate(360deg);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'attribute.value.css' }, + { startIndex: 28, type: 'attribute.value.number.css' }, + { startIndex: 31, type: 'attribute.value.unit.css' }, + { startIndex: 34, type: 'attribute.value.css' }, + { startIndex: 35, type: 'delimiter.css' } + ]}, { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' } + ]}, { + line: '}', + tokens: [ + { startIndex: 0, type: 'delimiter.bracket.css' } + ]}], + + // CSS @import related coloring bug 9553 + // @import url('something.css'); + // .rule1{} + // .rule2{} + [{ + line: '@import url(\"something.css\");', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.value.css' }, + { startIndex: 11, type: 'delimiter.parenthesis.css' }, + { startIndex: 12, type: 'string.css' }, + { startIndex: 27, type: 'delimiter.parenthesis.css' }, + { startIndex: 28, type: 'delimiter.css' } + ]}, { + line: '.rule1{}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 6, type: 'delimiter.bracket.css' }, + ]}, { + line: '.rule2{}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 6, type: 'delimiter.bracket.css' }, + ]}], + + // Triple quotes - bug #9870 + [{ + line: '"""', + tokens: [ + { startIndex: 0, type: 'string.css' } + ]}], + + [{ + line: '""""', + tokens: [ + { startIndex: 0, type: 'string.css' } + ]}], + + [{ + line: '"""""', + tokens: [ + { startIndex: 0, type: 'string.css' } + ]}], + + // import statement - bug #10308 + // @import url('something.css');@import url('something.css'); + [{ + line: '@import url(\"something.css\");@import url(\"something.css\");', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.value.css' }, + { startIndex: 11, type: 'delimiter.parenthesis.css' }, + { startIndex: 12, type: 'string.css' }, + { startIndex: 27, type: 'delimiter.parenthesis.css' }, + { startIndex: 28, type: 'delimiter.css' }, + { startIndex: 29, type: 'keyword.css' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'attribute.value.css' }, + { startIndex: 40, type: 'delimiter.parenthesis.css' }, + { startIndex: 41, type: 'string.css' }, + { startIndex: 56, type: 'delimiter.parenthesis.css' }, + { startIndex: 57, type: 'delimiter.css' } + ]}], + + // !important - bug #9578 + // .a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;} + [{ + line: '.a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 2, type: 'delimiter.bracket.css' }, + { startIndex: 3, type: 'attribute.name.css' }, + { startIndex: 14, type: 'attribute.value.hex.css' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'keyword.css' }, + { startIndex: 32, type: 'delimiter.bracket.css' }, + { startIndex: 33, type: 'tag.css' }, + { startIndex: 35, type: 'delimiter.bracket.css' }, + { startIndex: 36, type: 'attribute.name.css' }, + { startIndex: 48, type: 'string.css' }, + { startIndex: 64, type: 'delimiter.css' }, + { startIndex: 65, type: '' }, + { startIndex: 66, type: 'attribute.value.css' }, + { startIndex: 75, type: 'delimiter.css' }, + { startIndex: 76, type: 'attribute.name.css' }, + { startIndex: 83, type: 'attribute.value.number.css' }, + { startIndex: 85, type: 'attribute.value.unit.css' }, + { startIndex: 87, type: 'delimiter.css' }, + { startIndex: 88, type: 'delimiter.bracket.css' } + ]}], + + // base64-encoded data uris - bug #9580 + //.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom} + [{ + line: '.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}', + tokens: [ + {startIndex: 0, type: 'tag.css'}, + {startIndex: 5, type: ''}, + {startIndex: 6, type: 'delimiter.bracket.css'}, + {startIndex: 7, type: ''}, + {startIndex: 8, type: 'attribute.name.css'}, + {startIndex: 19, type: ''}, + {startIndex: 20, type: 'attribute.value.hex.css'}, + {startIndex: 24, type: ''}, + {startIndex: 25, type: 'attribute.value.css'}, + {startIndex: 28, type: 'delimiter.parenthesis.css'}, + {startIndex: 29, type: 'string.css'}, + {startIndex: 215, type: 'delimiter.parenthesis.css'}, + {startIndex: 216, type: ''}, + {startIndex: 217, type: 'attribute.value.css'}, + {startIndex: 225, type: ''}, + {startIndex: 226, type: 'attribute.value.css'}, + {startIndex: 232, type: 'delimiter.bracket.css'} + ]}], + + // /a colorization is incorrect in url - bug #9581 + //.a{background:url(/a.jpg)} + [{ + line: '.a{background:url(/a.jpg)}', + tokens: [ + {startIndex: 0, type: 'tag.css'}, + {startIndex: 2, type: 'delimiter.bracket.css'}, + {startIndex: 3, type: 'attribute.name.css'}, + {startIndex: 14, type: 'attribute.value.css'}, + {startIndex: 17, type: 'delimiter.parenthesis.css'}, + {startIndex: 18, type: 'string.css'}, + {startIndex: 24, type: 'delimiter.parenthesis.css'}, + {startIndex: 25, type: 'delimiter.bracket.css'} + ]}], + + // Bracket Matching + [{ + line: 'p{}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 1, type: 'delimiter.bracket.css' }, + ]}], + + [{ + line: 'p:nth() {}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 5, type: '' }, + { startIndex: 8, type: 'delimiter.bracket.css' } + ]}], +]);