├── .gitignore ├── LICENSE ├── README.md ├── demo ├── index.html ├── index.ts ├── modeSamples │ ├── html.ts │ ├── javascript.ts │ └── typescript.ts ├── package.json ├── tm │ ├── grammars │ │ ├── JavaScript.tmLanguage.json │ │ ├── TypeScript.tmLanguage.json │ │ ├── css.styled.tmLanguage.json │ │ ├── css.tmLanguage.json │ │ ├── html.tmLanguage.json │ │ ├── python.tmLanguage.json │ │ ├── smarty.tmLanguage.json │ │ └── styled.tmLanguage.json │ └── themes │ │ └── OneDark.tmTheme.json ├── tsconfig.json └── webpack.config.js ├── package.json ├── src ├── Highlighter.ts ├── index.ts └── tmToCm.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Build output 40 | dist/ 41 | 42 | # TypeScript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # npm/yarn lock files 58 | package-lock.json 59 | yarn.lock 60 | 61 | # Yarn Integrity file 62 | .yarn-integrity 63 | 64 | # dotenv environment variables file 65 | .env 66 | 67 | # parcel-bundler cache (https://parceljs.org/) 68 | .cache 69 | 70 | # next.js build output 71 | .next 72 | 73 | # nuxt.js build output 74 | .nuxt 75 | 76 | # vuepress build output 77 | .vuepress/dist 78 | 79 | # Serverless directories 80 | .serverless 81 | 82 | # FuseBox cache 83 | .fusebox/ 84 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Neek Sandhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Textmate grammars support for CodeMirror 2 | 3 | Bring TM grammar driven tokenization to your CodeMirror editors. 4 | 5 | Say goodbye to the not-so-cool and not-so-accurate syntax highlighting you've been living with and up your game with ease! 6 | 7 | ### WARNING 8 | 9 | This package will only work in browsers with `WebAssembly` support. Here's a recommended way to deal with it: 10 | 11 | ```javascript 12 | // 95% of your target audience (developers) 13 | if ('WebAssembly' in window) { 14 | const [{ 15 | loadWASM 16 | }, 17 | { 18 | activateLanguage, 19 | addGrammar 20 | } 21 | ] = await Promise.all([ 22 | import('onigasm'), 23 | import('codemirror-textmate'), 24 | ]) 25 | 26 | // ... (see https://www.npmjs.com/package/onigasm#light-it-up) 27 | // ... (see example code below) 28 | } 29 | // Fallback for rest 5% 30 | else { 31 | await Promise.all([ 32 | import('codemirror/mode/javascript/javascript'), 33 | import( 'codemirror/mode/htmlmixed/htmlmixed'), 34 | ]) 35 | } 36 | 37 | const editor = CodeMirror.fromTextArea( /* ... */ ) 38 | // ... (go on as usual) 39 | ``` 40 | 41 | ## Usage 42 | 43 | ### Install 44 | 45 | ```bash 46 | $ npm i codemirror-textmate 47 | 48 | # Install peer dependencies if you haven't already 49 | npm i onigasm codemirror 50 | ``` 51 | 52 | See `./demo/index.ts` for instructions on how to light it up! 53 | 54 | ## API 55 | 56 | This package is written in TypeScript and is published with TS declaration files. Once you install the package 57 | see `node_modules/codemirror-textmate/dist/typings/index.d.ts` for available stuff along with expected data types. 58 | 59 | VSCode's intellisense will also pick up the declaration files and guide you nicely with auto-complete and errors. 60 | 61 | ## License 62 | 63 | MIT 64 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CodeMirror TextMate Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /demo/index.ts: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from 'codemirror' 2 | import { loadWASM } from 'onigasm' 3 | 4 | import 'codemirror/lib/codemirror.css' 5 | 6 | import { 7 | activateLanguage, 8 | addGrammar, 9 | 10 | // [ optional | recommended ] Textmate themes in CodeMirror 11 | addTheme, 12 | ITextmateThemePlus, 13 | // [ optional ] Grammar injections 14 | linkInjections, 15 | } from 'codemirror-textmate' 16 | 17 | (async () => { 18 | await loadWASM( 19 | // webpack has been configured to resolve `.wasm` files to actual 'paths" as opposed to using the built-in wasm-loader 20 | // oniguruma is a low-level library and stock wasm-loader isn't equipped with advanced low-level API's to interact with libonig 21 | require('onigasm/lib/onigasm.wasm')) 22 | 23 | const grammars = { 24 | // loading `source.js` as a standalone grammar and as dependency of `text.html.basic` 25 | 'source.js': { 26 | /** 27 | * This the most resource efficient way to load grammars as of yet 28 | */ 29 | loader: () => import('./tm/grammars/Javascript.tmLanguage.json'), 30 | 31 | /** 32 | * Language ID is only necessary for languages you want to use as CodeMirror mode (eg: cm.setOption('mode', 'javascript')) 33 | * To do that, we use `activatelanguage`, which will link one scope name to a language ID (also known as "mode") 34 | * 35 | * Grammar dependencies don't need to be "activated", just "adding/registering" them is enough (using `addGrammar`) 36 | */ 37 | language: 'javascript', 38 | 39 | /** 40 | * Third parameter accepted by `activateLanguage` to specify language loading priority 41 | * Loading priority can be 'now' | 'asap' | 'defer' (default) 42 | * 43 | * - [HIGH] 'now' will cause the language (and it's grammars) to load/compile right away (most likely in the next event loop) 44 | * - [MED] 'asap' is like 'now' but will use `requestIdleCallback` if available (fallbacks to `setTimeout`, 10 seconds). 45 | * - [LOW] 'defer' will only do registeration and loading/compiling is deferred until needed (⚠ WILL CAUSE FOUC IN CODEMIRROR) (DEFAULT) 46 | */ 47 | priority: 'now' 48 | }, 49 | 50 | // loading `source.css` as a standalone grammar and as dependency of `text.html.basic` 51 | 'source.ts': { 52 | loader: () => import('./tm/grammars/TypeScript.tmLanguage.json'), 53 | language: 'typescript', 54 | priority: 'asap' 55 | }, 56 | 57 | // loading `source.css` as a standalone grammar and as dependency of `text.html.basic` 58 | 'source.css': { 59 | loader: () => import('./tm/grammars/css.tmLanguage.json'), 60 | language: 'css', 61 | priority: 'now' 62 | }, 63 | 64 | // Secondary dependency of `text.html.basic` 65 | 'source.smarty': { 66 | loader: () => import('./tm/grammars/smarty.tmLanguage.json'), 67 | // priority of dependenices like this one are regulated by dependent grammars 68 | }, 69 | // Secondary dependency of `text.html.basic` 70 | // (can be also be used for tokenizing python source code, just add `language` property below) 71 | 'source.python': { 72 | loader: () => import('./tm/grammars/python.tmLanguage.json'), 73 | }, 74 | 75 | // Some grammars have other grammars as dependencies. You must register those deps with `addGrammar` or it will throw an Error 76 | 'text.html.basic': { 77 | loader: () => import('./tm/grammars/html.tmLanguage.json'), 78 | language: 'html', 79 | priority: 'asap', 80 | } 81 | 82 | } 83 | 84 | // To avoid FOUC, await for high priority languages to get ready (loading/compiling takes time, and it's an async process for which CM won't wait) 85 | await Promise.all(Object.keys(grammars).map(async scopeName => { 86 | const { loader, language, priority } = grammars[scopeName] 87 | 88 | addGrammar(scopeName, loader) 89 | 90 | if (language) { 91 | const prom = activateLanguage(scopeName, language, priority) 92 | 93 | // We must "wait" for high priority languages to load/compile before we render editor to avoid FOUC (Flash of Unstyled Content) 94 | if (priority === 'now') { 95 | await prom 96 | } 97 | 98 | // 'asap' although "awaitable", is a medium priority, and doesn't need to be waited for 99 | // 'defer' doesn't support awaiting at all 100 | return 101 | } 102 | })) 103 | 104 | const editor = CodeMirror.fromTextArea(document.getElementById('cm-host') as HTMLTextAreaElement, { 105 | lineNumbers: true, 106 | // If you know in advance a language is going to be set on CodeMirror editor and it isn't preloaded by setting the third argument 107 | // to `activateLanguage` to 'now', the contents of the editor would start of and remain as unhighlighted text, until loading is complete 108 | mode: 'typescript' 109 | }) 110 | editor.setValue((await import('./modeSamples/typescript')).default) 111 | 112 | // Everything should be working now! 113 | 114 | ////////////////////////////////////////////////////// 115 | 116 | // ____ __ _ __ 117 | // / __ \____ / /_(_)___ ____ ____ _/ / 118 | // / / / / __ \/ __/ / __ \/ __ \/ __ `/ / 119 | // / /_/ / /_/ / /_/ / /_/ / / / / /_/ / / 120 | // \____/ .___/\__/_/\____/_/ /_/\__,_/_/ 121 | // /_/ 122 | 123 | // Using Textmate theme in CodeMirror 124 | const themeX: ITextmateThemePlus = { 125 | ...(await import('./tm/themes/OneDark.tmTheme.json')), 126 | gutterSettings: { 127 | background: '#1d1f25', 128 | divider: '#1d1f25' 129 | } 130 | } 131 | addTheme(themeX) 132 | editor.setOption('theme', themeX.name) 133 | 134 | // Grammar injections, example code below will highlight css-in-js (styled-components, emotion) 135 | // injections are "injections", they are not standalone-grammars, therefore no `activateLanguage` 136 | addGrammar('source.css.styled', () => import('./tm/grammars/css.styled.tmLanguage.json') as any) 137 | addGrammar('styled', () => import('./tm/grammars/styled.tmLanguage.json') as any) 138 | 139 | const affectedLanguages = await linkInjections('styled', ['source.ts', 'source.tsx', 'source.js', 'source.jsx']) 140 | 141 | // You must re-trigger tokenization to apply the update above (if applicable) 142 | const activeMode = editor.getOption('mode') 143 | if (affectedLanguages.indexOf(activeMode) > -1) { 144 | // Resetting cm's mode re-triggers tokenization of entire document 145 | editor.setOption('mode', activeMode) 146 | } 147 | })() 148 | -------------------------------------------------------------------------------- /demo/modeSamples/html.ts: -------------------------------------------------------------------------------- 1 | export default `\ 2 | 3 | 4 | 5 | 6 | 7 | CodeMirror TextMate Demo 8 | 9 | 10 | 11 | 12 | 13 | ` -------------------------------------------------------------------------------- /demo/modeSamples/javascript.ts: -------------------------------------------------------------------------------- 1 | export default `\ 2 | function test() { 3 | const string = 'nice' 4 | const number = 1243 5 | const boolean = false 6 | const templateLiteral = \`noice${12} mate\` 7 | const func = (a, b) => a + b 8 | } 9 | 10 | class AwesomeMap extends Map { 11 | isKeyOfType(key, type) { 12 | return typeof this.get(key) === type 13 | } 14 | } 15 | ` -------------------------------------------------------------------------------- /demo/modeSamples/typescript.ts: -------------------------------------------------------------------------------- 1 | export default `\ 2 | interface IEatable { 3 | chew(speed?: number): Promise 4 | swallow(ensureChewed?: boolean): Promise 5 | } 6 | 7 | function test() { 8 | const string: string = 'nice' 9 | const number: number = 1243 10 | const boolean: boolean = false 11 | const templateLiteral: string = \`noice ${'${12}'} mate\` 12 | const func = (a: number, b: number) => a + b 13 | } 14 | 15 | class AwesomeMap extends Map { 16 | public isKeyOfType(key: string, type: string) { 17 | return typeof this.get(key) === type 18 | } 19 | } 20 | ` -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "npm run __build-cm-tm && webpack-dev-server .", 4 | "__build-cm-tm": "tsc --build ../tsconfig.json" 5 | }, 6 | "private": true, 7 | "license": "MIT", 8 | "dependencies": { 9 | "codemirror": "^5.43.0", 10 | "codemirror-textmate": "file:..", 11 | "onigasm": "^2.2.1" 12 | }, 13 | "devDependencies": { 14 | "@types/node": "^10.12.21", 15 | "css-loader": "^2.1.0", 16 | "file-loader": "^3.0.1", 17 | "html-webpack-plugin": "^3.2.0", 18 | "style-loader": "^0.23.1", 19 | "ts-loader": "^5.3.3", 20 | "typescript": "^3.3.1", 21 | "webpack": "^4.29.0", 22 | "webpack-cli": "^3.2.1", 23 | "webpack-dev-server": "^3.1.14" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /demo/tm/grammars/css.styled.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 | "name": "CSS (Styled Components)", 4 | "patterns": [ 5 | { 6 | "include": "#general" 7 | }, 8 | { 9 | "include": "#rules" 10 | }, 11 | { 12 | "include": "#property_list" 13 | }, 14 | { 15 | "include": "#at_rule_media" 16 | }, 17 | { 18 | "include": "#at_rule_import" 19 | }, 20 | { 21 | "include": "#at_rule_fontface" 22 | }, 23 | { 24 | "include": "#at_rule_page" 25 | }, 26 | { 27 | "include": "#at_rule_keyframes" 28 | }, 29 | { 30 | "include": "#at_rule_supports" 31 | }, 32 | { 33 | "match": ";", 34 | "name": "punctuation.terminator.rule.css" 35 | }, 36 | { 37 | "include": "#properties" 38 | } 39 | ], 40 | "repository": { 41 | "at_rule_fontface": { 42 | "patterns": [ 43 | { 44 | "begin": "^\\s*((@)font-face\\b)", 45 | "beginCaptures": { 46 | "1": { 47 | "name": "keyword.control.at-rule.fontface.scss" 48 | }, 49 | "2": { 50 | "name": "punctuation.definition.keyword.scss" 51 | } 52 | }, 53 | "end": "\\s*(?={)", 54 | "name": "meta.at-rule.fontface.scss", 55 | "patterns": [ 56 | { 57 | "include": "#function_attributes" 58 | } 59 | ] 60 | } 61 | ] 62 | }, 63 | "at_rule_import": { 64 | "begin": "\\s*((@)import\\b)\\s*", 65 | "captures": { 66 | "1": { 67 | "name": "keyword.control.at-rule.import.scss" 68 | }, 69 | "2": { 70 | "name": "punctuation.definition.keyword.scss" 71 | } 72 | }, 73 | "end": "\\s*((?=;)|(?=}))", 74 | "name": "meta.at-rule.import.scss", 75 | "patterns": [ 76 | { 77 | "include": "#interpolation" 78 | }, 79 | { 80 | "include": "#string_single" 81 | }, 82 | { 83 | "include": "#string_double" 84 | }, 85 | { 86 | "include": "#functions" 87 | } 88 | ] 89 | }, 90 | "at_rule_keyframes": { 91 | "begin": "(?<=^|\\s)(@)(?:-(?:webkit|moz)-)?keyframes\\b", 92 | "beginCaptures": { 93 | "0": { 94 | "name": "keyword.control.at-rule.keyframes.scss" 95 | }, 96 | "1": { 97 | "name": "punctuation.definition.keyword.scss" 98 | } 99 | }, 100 | "end": "(?<=})", 101 | "name": "meta.at-rule.keyframes.scss", 102 | "patterns": [ 103 | { 104 | "match": "(?<=@keyframes)\\s+((?:[_A-Za-z][-\\w]|-[_A-Za-z])[-\\w]*)", 105 | "captures": { 106 | "1": { 107 | "name": "entity.name.function.scss" 108 | } 109 | } 110 | }, 111 | { 112 | "begin": "(?<=@keyframes)\\s+(\")", 113 | "beginCaptures": { 114 | "1": { 115 | "name": "punctuation.definition.string.begin.scss" 116 | } 117 | }, 118 | "end": "\"", 119 | "endCaptures": { 120 | "0": { 121 | "name": "punctuation.definition.string.end.scss" 122 | } 123 | }, 124 | "name": "string.quoted.double.scss", 125 | "contentName": "entity.name.function.scss", 126 | "patterns": [ 127 | { 128 | "match": "\\\\(\\h{1,6}|.)", 129 | "name": "constant.character.escape.scss" 130 | }, 131 | { 132 | "include": "#interpolation" 133 | } 134 | ] 135 | }, 136 | { 137 | "begin": "(?<=@keyframes)\\s+(')", 138 | "beginCaptures": { 139 | "1": { 140 | "name": "punctuation.definition.string.begin.scss" 141 | } 142 | }, 143 | "end": "'", 144 | "endCaptures": { 145 | "0": { 146 | "name": "punctuation.definition.string.end.scss" 147 | } 148 | }, 149 | "name": "string.quoted.single.scss", 150 | "contentName": "entity.name.function.scss", 151 | "patterns": [ 152 | { 153 | "match": "\\\\(\\h{1,6}|.)", 154 | "name": "constant.character.escape.scss" 155 | }, 156 | { 157 | "include": "#interpolation" 158 | } 159 | ] 160 | }, 161 | { 162 | "begin": "{", 163 | "beginCaptures": { 164 | "0": { 165 | "name": "punctuation.section.keyframes.begin.scss" 166 | } 167 | }, 168 | "end": "}", 169 | "endCaptures": { 170 | "0": { 171 | "name": "punctuation.section.keyframes.end.scss" 172 | } 173 | }, 174 | "patterns": [ 175 | { 176 | "match": "\\b(?:(?:100|[1-9]\\d|\\d)%|from|to)(?=\\s*{)", 177 | "name": "entity.other.attribute-name.scss" 178 | }, 179 | { 180 | "include": "#interpolation" 181 | }, 182 | { 183 | "include": "#property_list" 184 | }, 185 | { 186 | "include": "#rules" 187 | } 188 | ] 189 | } 190 | ] 191 | }, 192 | "at_rule_media": { 193 | "patterns": [ 194 | { 195 | "begin": "^\\s*((@)media)\\b", 196 | "beginCaptures": { 197 | "1": { 198 | "name": "keyword.control.at-rule.media.scss" 199 | }, 200 | "2": { 201 | "name": "punctuation.definition.keyword.scss" 202 | } 203 | }, 204 | "end": "\\s*(?={)", 205 | "name": "meta.at-rule.media.scss", 206 | "patterns": [ 207 | { 208 | "include": "#comment_block" 209 | }, 210 | { 211 | "match": "\\b(only)\\b", 212 | "name": "keyword.control.operator.css.scss" 213 | }, 214 | { 215 | "begin": "\\(", 216 | "beginCaptures": { 217 | "0": { 218 | "name": "punctuation.definition.media-query.begin.bracket.round.scss" 219 | } 220 | }, 221 | "end": "\\)", 222 | "endCaptures": { 223 | "0": { 224 | "name": "punctuation.definition.media-query.end.bracket.round.scss" 225 | } 226 | }, 227 | "name": "meta.property-list.media-query.scss", 228 | "patterns": [ 229 | { 230 | "begin": "(?=|<|>", 676 | "name": "keyword.operator.comparison.scss" 677 | }, 678 | "logical_operators": { 679 | "match": "\\b(not|or|and)\\b", 680 | "name": "keyword.operator.logical.scss" 681 | }, 682 | "operators": { 683 | "match": "[-+*/](?!\\s*[-+*/])", 684 | "name": "keyword.operator.css" 685 | }, 686 | "properties": { 687 | "patterns": [ 688 | { 689 | "begin": "(?+~|] # - Another selector\n | /\\* # - A block comment\n)", 915 | "name": "entity.other.attribute-name.class.css", 916 | "captures": { 917 | "1": { 918 | "name": "punctuation.definition.entity.css" 919 | }, 920 | "2": { 921 | "patterns": [ 922 | { 923 | "include": "#interpolation" 924 | }, 925 | { 926 | "match": "\\\\([0-9a-fA-F]{1,6}|.)", 927 | "name": "constant.character.escape.scss" 928 | }, 929 | { 930 | "match": "\\$|}", 931 | "name": "invalid.illegal.scss" 932 | } 933 | ] 934 | } 935 | } 936 | }, 937 | "selector_custom": { 938 | "match": "\\b([a-zA-Z0-9]+(-[a-zA-Z0-9]+)+)(?=\\.|\\s++[^:]|\\s*[,\\[{]|:(link|visited|hover|active|focus|target|lang|disabled|enabled|checked|indeterminate|root|nth-(child|last-child|of-type|last-of-type)|first-child|last-child|first-of-type|last-of-type|only-child|only-of-type|empty|not|valid|invalid)(\\([0-9A-Za-z]*\\))?)", 939 | "name": "entity.name.tag.custom.scss" 940 | }, 941 | "selector_id": { 942 | "match": "(?x)\n(\\#) # Valid id-name\n(\n (?: [-a-zA-Z_0-9]|[^\\x00-\\x7F] # Valid identifier characters\n | \\\\(?:[0-9a-fA-F]{1,6}|.) # Escape sequence\n|\\$\\{[^{}]*\\} # Interpolation\n )+\n) # Followed by either:\n(?= $ # - End of the line\n | [\\s,.\\#)\\[:{>+~|] # - Another selector\n | /\\* # - A block comment\n)", 943 | "name": "entity.other.attribute-name.id.css", 944 | "captures": { 945 | "1": { 946 | "name": "punctuation.definition.entity.css" 947 | }, 948 | "2": { 949 | "patterns": [ 950 | { 951 | "include": "#interpolation" 952 | }, 953 | { 954 | "match": "\\\\([0-9a-fA-F]{1,6}|.)", 955 | "name": "constant.character.escape.scss" 956 | }, 957 | { 958 | "match": "\\$|}", 959 | "name": "invalid.illegal.identifier.scss" 960 | } 961 | ] 962 | } 963 | } 964 | }, 965 | "parent_selector_suffix": { 966 | "match": "(?x)\n(?<=&)\n(\n (?: [-a-zA-Z_0-9]|[^\\x00-\\x7F] # Valid identifier characters\n | \\\\(?:[0-9a-fA-F]{1,6}|.) # Escape sequence\n|\\$\\{[^{}]*\\} # Interpolation\n )+\n) # Followed by either:\n(?= $ # - End of the line\n | [\\s,.\\#)\\[:{>+~|] # - Another selector\n | /\\* # - A block comment\n)", 967 | "name": "entity.other.attribute-name.parent-selector-suffix.css", 968 | "captures": { 969 | "1": { 970 | "name": "punctuation.definition.entity.css" 971 | }, 972 | "2": { 973 | "patterns": [ 974 | { 975 | "include": "#interpolation" 976 | }, 977 | { 978 | "match": "\\\\([0-9a-fA-F]{1,6}|.)", 979 | "name": "constant.character.escape.scss" 980 | }, 981 | { 982 | "match": "\\$|}", 983 | "name": "invalid.illegal.identifier.scss" 984 | } 985 | ] 986 | } 987 | } 988 | }, 989 | "selector_pseudo_class": { 990 | "patterns": [ 991 | { 992 | "begin": "((:)\\bnth-(?:child|last-child|of-type|last-of-type))(\\()", 993 | "beginCaptures": { 994 | "1": { 995 | "name": "entity.other.attribute-name.pseudo-class.css" 996 | }, 997 | "2": { 998 | "name": "punctuation.definition.entity.css" 999 | }, 1000 | "3": { 1001 | "name": "punctuation.definition.pseudo-class.begin.bracket.round.css" 1002 | } 1003 | }, 1004 | "end": "\\)", 1005 | "endCaptures": { 1006 | "0": { 1007 | "name": "punctuation.definition.pseudo-class.end.bracket.round.css" 1008 | } 1009 | }, 1010 | "patterns": [ 1011 | { 1012 | "include": "#interpolation" 1013 | }, 1014 | { 1015 | "match": "\\d+", 1016 | "name": "constant.numeric.css" 1017 | }, 1018 | { 1019 | "match": "(?<=\\d)n\\b|\\b(n|even|odd)\\b", 1020 | "name": "constant.other.scss" 1021 | }, 1022 | { 1023 | "match": "\\w+", 1024 | "name": "invalid.illegal.scss" 1025 | } 1026 | ] 1027 | }, 1028 | { 1029 | "include": "source.css#pseudo-classes" 1030 | }, 1031 | { 1032 | "include": "source.css#pseudo-elements" 1033 | }, 1034 | { 1035 | "include": "source.css#functional-pseudo-classes" 1036 | } 1037 | ] 1038 | }, 1039 | "selectors": { 1040 | "patterns": [ 1041 | { 1042 | "include": "#interpolation" 1043 | }, 1044 | { 1045 | "include": "source.css#tag-names" 1046 | }, 1047 | { 1048 | "include": "#selector_custom" 1049 | }, 1050 | { 1051 | "include": "#selector_class" 1052 | }, 1053 | { 1054 | "include": "#selector_id" 1055 | }, 1056 | { 1057 | "include": "#selector_pseudo_class" 1058 | }, 1059 | { 1060 | "include": "#tag_wildcard" 1061 | }, 1062 | { 1063 | "include": "#tag_parent_reference" 1064 | }, 1065 | { 1066 | "include": "source.css#pseudo-elements" 1067 | }, 1068 | { 1069 | "include": "#selector_attribute" 1070 | }, 1071 | { 1072 | "include": "#parent_selector_suffix" 1073 | } 1074 | ] 1075 | }, 1076 | "string_double": { 1077 | "begin": "\"", 1078 | "beginCaptures": { 1079 | "0": { 1080 | "name": "punctuation.definition.string.begin.scss" 1081 | } 1082 | }, 1083 | "end": "\"", 1084 | "endCaptures": { 1085 | "0": { 1086 | "name": "punctuation.definition.string.end.scss" 1087 | } 1088 | }, 1089 | "name": "string.quoted.double.scss", 1090 | "patterns": [ 1091 | { 1092 | "match": "\\\\(\\h{1,6}|.)", 1093 | "name": "constant.character.escape.scss" 1094 | }, 1095 | { 1096 | "include": "#interpolation" 1097 | } 1098 | ] 1099 | }, 1100 | "string_single": { 1101 | "begin": "'", 1102 | "beginCaptures": { 1103 | "0": { 1104 | "name": "punctuation.definition.string.begin.scss" 1105 | } 1106 | }, 1107 | "end": "'", 1108 | "endCaptures": { 1109 | "0": { 1110 | "name": "punctuation.definition.string.end.scss" 1111 | } 1112 | }, 1113 | "name": "string.quoted.single.scss", 1114 | "patterns": [ 1115 | { 1116 | "match": "\\\\(\\h{1,6}|.)", 1117 | "name": "constant.character.escape.scss" 1118 | }, 1119 | { 1120 | "include": "#interpolation" 1121 | } 1122 | ] 1123 | }, 1124 | "tag_parent_reference": { 1125 | "match": "&", 1126 | "name": "entity.name.tag.reference.scss" 1127 | }, 1128 | "tag_wildcard": { 1129 | "match": "\\*", 1130 | "name": "entity.name.tag.wildcard.scss" 1131 | } 1132 | }, 1133 | 1134 | "scopeName": "source.css.styled" 1135 | } -------------------------------------------------------------------------------- /demo/tm/grammars/css.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "information_for_contributors": [ 3 | "This file has been converted from https://github.com/atom/language-css/blob/master/grammars/css.cson", 4 | "If you want to provide a fix or improvement, please create a pull request against the original repository.", 5 | "Once accepted there, we are happy to receive an update request." 6 | ], 7 | "version": "https://github.com/atom/language-css/commit/2bc1e294e2440ad91197263cd9f95dc4b00bab2f", 8 | "name": "CSS", 9 | "scopeName": "source.css", 10 | "patterns": [ 11 | { 12 | "include": "#comment-block" 13 | }, 14 | { 15 | "include": "#escapes" 16 | }, 17 | { 18 | "include": "#combinators" 19 | }, 20 | { 21 | "include": "#selector" 22 | }, 23 | { 24 | "include": "#at-rules" 25 | }, 26 | { 27 | "include": "#rule-list" 28 | } 29 | ], 30 | "repository": { 31 | "at-rules": { 32 | "patterns": [ 33 | { 34 | "begin": "\\A(?:\\xEF\\xBB\\xBF)?(?i:(?=\\s*@charset\\b))", 35 | "end": ";|(?=$)", 36 | "endCaptures": { 37 | "0": { 38 | "name": "punctuation.terminator.rule.css" 39 | } 40 | }, 41 | "name": "meta.at-rule.charset.css", 42 | "patterns": [ 43 | { 44 | "captures": { 45 | "1": { 46 | "name": "invalid.illegal.not-lowercase.charset.css" 47 | }, 48 | "2": { 49 | "name": "invalid.illegal.leading-whitespace.charset.css" 50 | }, 51 | "3": { 52 | "name": "invalid.illegal.no-whitespace.charset.css" 53 | }, 54 | "4": { 55 | "name": "invalid.illegal.whitespace.charset.css" 56 | }, 57 | "5": { 58 | "name": "invalid.illegal.not-double-quoted.charset.css" 59 | }, 60 | "6": { 61 | "name": "invalid.illegal.unclosed-string.charset.css" 62 | }, 63 | "7": { 64 | "name": "invalid.illegal.unexpected-characters.charset.css" 65 | } 66 | }, 67 | "match": "(?x) # Possible errors:\n\\G\n((?!@charset)@\\w+) # Not lowercase (@charset is case-sensitive)\n|\n\\G(\\s+) # Preceding whitespace\n|\n(@charset\\S[^;]*) # No whitespace after @charset\n|\n(?<=@charset) # Before quoted charset name\n(\\x20{2,}|\\t+) # More than one space used, or a tab\n|\n(?<=@charset\\x20) # Beginning of charset name\n([^\";]+) # Not double-quoted\n|\n(\"[^\"]+$) # Unclosed quote\n|\n(?<=\") # After charset name\n([^;]+) # Unexpected junk instead of semicolon" 68 | }, 69 | { 70 | "captures": { 71 | "1": { 72 | "name": "keyword.control.at-rule.charset.css" 73 | }, 74 | "2": { 75 | "name": "punctuation.definition.keyword.css" 76 | } 77 | }, 78 | "match": "((@)charset)(?=\\s)" 79 | }, 80 | { 81 | "begin": "\"", 82 | "beginCaptures": { 83 | "0": { 84 | "name": "punctuation.definition.string.begin.css" 85 | } 86 | }, 87 | "end": "\"|$", 88 | "endCaptures": { 89 | "0": { 90 | "name": "punctuation.definition.string.end.css" 91 | } 92 | }, 93 | "name": "string.quoted.double.css", 94 | "patterns": [ 95 | { 96 | "begin": "(?:\\G|^)(?=(?:[^\"])+$)", 97 | "end": "$", 98 | "name": "invalid.illegal.unclosed.string.css" 99 | } 100 | ] 101 | } 102 | ] 103 | }, 104 | { 105 | "begin": "(?i)((@)import)(?:\\s+|$|(?=['\"]|/\\*))", 106 | "beginCaptures": { 107 | "1": { 108 | "name": "keyword.control.at-rule.import.css" 109 | }, 110 | "2": { 111 | "name": "punctuation.definition.keyword.css" 112 | } 113 | }, 114 | "end": ";", 115 | "endCaptures": { 116 | "0": { 117 | "name": "punctuation.terminator.rule.css" 118 | } 119 | }, 120 | "name": "meta.at-rule.import.css", 121 | "patterns": [ 122 | { 123 | "begin": "\\G\\s*(?=/\\*)", 124 | "end": "(?<=\\*/)\\s*", 125 | "patterns": [ 126 | { 127 | "include": "#comment-block" 128 | } 129 | ] 130 | }, 131 | { 132 | "include": "#string" 133 | }, 134 | { 135 | "include": "#url" 136 | }, 137 | { 138 | "include": "#media-query-list" 139 | } 140 | ] 141 | }, 142 | { 143 | "begin": "(?i)((@)font-face)(?=\\s*|{|/\\*|$)", 144 | "beginCaptures": { 145 | "1": { 146 | "name": "keyword.control.at-rule.font-face.css" 147 | }, 148 | "2": { 149 | "name": "punctuation.definition.keyword.css" 150 | } 151 | }, 152 | "end": "(?!\\G)", 153 | "name": "meta.at-rule.font-face.css", 154 | "patterns": [ 155 | { 156 | "include": "#comment-block" 157 | }, 158 | { 159 | "include": "#escapes" 160 | }, 161 | { 162 | "include": "#rule-list" 163 | } 164 | ] 165 | }, 166 | { 167 | "begin": "(?i)(@)page(?=[\\s:{]|/\\*|$)", 168 | "captures": { 169 | "0": { 170 | "name": "keyword.control.at-rule.page.css" 171 | }, 172 | "1": { 173 | "name": "punctuation.definition.keyword.css" 174 | } 175 | }, 176 | "end": "(?=\\s*($|[:{;]))", 177 | "name": "meta.at-rule.page.css", 178 | "patterns": [ 179 | { 180 | "include": "#rule-list" 181 | } 182 | ] 183 | }, 184 | { 185 | "begin": "(?i)(?=@media(\\s|\\(|/\\*|$))", 186 | "end": "(?<=})(?!\\G)", 187 | "patterns": [ 188 | { 189 | "begin": "(?i)\\G(@)media", 190 | "beginCaptures": { 191 | "0": { 192 | "name": "keyword.control.at-rule.media.css" 193 | }, 194 | "1": { 195 | "name": "punctuation.definition.keyword.css" 196 | } 197 | }, 198 | "end": "(?=\\s*[{;])", 199 | "name": "meta.at-rule.media.header.css", 200 | "patterns": [ 201 | { 202 | "include": "#media-query-list" 203 | } 204 | ] 205 | }, 206 | { 207 | "begin": "{", 208 | "beginCaptures": { 209 | "0": { 210 | "name": "punctuation.section.media.begin.bracket.curly.css" 211 | } 212 | }, 213 | "end": "}", 214 | "endCaptures": { 215 | "0": { 216 | "name": "punctuation.section.media.end.bracket.curly.css" 217 | } 218 | }, 219 | "name": "meta.at-rule.media.body.css", 220 | "patterns": [ 221 | { 222 | "include": "$self" 223 | } 224 | ] 225 | } 226 | ] 227 | }, 228 | { 229 | "begin": "(?i)(?=@counter-style([\\s'\"{;]|/\\*|$))", 230 | "end": "(?<=})(?!\\G)", 231 | "patterns": [ 232 | { 233 | "begin": "(?i)\\G(@)counter-style", 234 | "beginCaptures": { 235 | "0": { 236 | "name": "keyword.control.at-rule.counter-style.css" 237 | }, 238 | "1": { 239 | "name": "punctuation.definition.keyword.css" 240 | } 241 | }, 242 | "end": "(?=\\s*{)", 243 | "name": "meta.at-rule.counter-style.header.css", 244 | "patterns": [ 245 | { 246 | "include": "#comment-block" 247 | }, 248 | { 249 | "include": "#escapes" 250 | }, 251 | { 252 | "captures": { 253 | "0": { 254 | "patterns": [ 255 | { 256 | "include": "#escapes" 257 | } 258 | ] 259 | } 260 | }, 261 | "match": "(?x)\n(?:[-a-zA-Z_] | [^\\x00-\\x7F]) # First letter\n(?:[-a-zA-Z0-9_] | [^\\x00-\\x7F] # Remainder of identifier\n |\\\\(?:[0-9a-fA-F]{1,6}|.)\n)*", 262 | "name": "variable.parameter.style-name.css" 263 | } 264 | ] 265 | }, 266 | { 267 | "begin": "{", 268 | "beginCaptures": { 269 | "0": { 270 | "name": "punctuation.section.property-list.begin.bracket.curly.css" 271 | } 272 | }, 273 | "end": "}", 274 | "endCaptures": { 275 | "0": { 276 | "name": "punctuation.section.property-list.end.bracket.curly.css" 277 | } 278 | }, 279 | "name": "meta.at-rule.counter-style.body.css", 280 | "patterns": [ 281 | { 282 | "include": "#comment-block" 283 | }, 284 | { 285 | "include": "#escapes" 286 | }, 287 | { 288 | "include": "#rule-list-innards" 289 | } 290 | ] 291 | } 292 | ] 293 | }, 294 | { 295 | "begin": "(?i)(?=@document([\\s'\"{;]|/\\*|$))", 296 | "end": "(?<=})(?!\\G)", 297 | "patterns": [ 298 | { 299 | "begin": "(?i)\\G(@)document", 300 | "beginCaptures": { 301 | "0": { 302 | "name": "keyword.control.at-rule.document.css" 303 | }, 304 | "1": { 305 | "name": "punctuation.definition.keyword.css" 306 | } 307 | }, 308 | "end": "(?=\\s*[{;])", 309 | "name": "meta.at-rule.document.header.css", 310 | "patterns": [ 311 | { 312 | "begin": "(?i)(?>>", 634 | "name": "invalid.deprecated.combinator.css" 635 | }, 636 | { 637 | "match": ">>|>|\\+|~", 638 | "name": "keyword.operator.combinator.css" 639 | } 640 | ] 641 | }, 642 | "commas": { 643 | "match": ",", 644 | "name": "punctuation.separator.list.comma.css" 645 | }, 646 | "comment-block": { 647 | "begin": "/\\*", 648 | "beginCaptures": { 649 | "0": { 650 | "name": "punctuation.definition.comment.begin.css" 651 | } 652 | }, 653 | "end": "\\*/", 654 | "endCaptures": { 655 | "0": { 656 | "name": "punctuation.definition.comment.end.css" 657 | } 658 | }, 659 | "name": "comment.block.css" 660 | }, 661 | "escapes": { 662 | "patterns": [ 663 | { 664 | "match": "\\\\[0-9a-fA-F]{1,6}", 665 | "name": "constant.character.escape.codepoint.css" 666 | }, 667 | { 668 | "begin": "\\\\$\\s*", 669 | "end": "^(?<:=]|\\)|/\\*) # Terminates cleanly" 1207 | }, 1208 | "media-feature-keywords": { 1209 | "match": "(?xi)\n(?<=^|\\s|:|\\*/)\n(?: portrait # Orientation\n | landscape\n | progressive # Scan types\n | interlace\n | fullscreen # Display modes\n | standalone\n | minimal-ui\n | browser\n)\n(?=\\s|\\)|$)", 1210 | "name": "support.constant.property-value.css" 1211 | }, 1212 | "media-query": { 1213 | "begin": "\\G", 1214 | "end": "(?=\\s*[{;])", 1215 | "patterns": [ 1216 | { 1217 | "include": "#comment-block" 1218 | }, 1219 | { 1220 | "include": "#escapes" 1221 | }, 1222 | { 1223 | "include": "#media-types" 1224 | }, 1225 | { 1226 | "match": "(?i)(?<=\\s|^|,|\\*/)(only|not)(?=\\s|{|/\\*|$)", 1227 | "name": "keyword.operator.logical.$1.media.css" 1228 | }, 1229 | { 1230 | "match": "(?i)(?<=\\s|^|\\*/|\\))and(?=\\s|/\\*|$)", 1231 | "name": "keyword.operator.logical.and.media.css" 1232 | }, 1233 | { 1234 | "match": ",(?:(?:\\s*,)+|(?=\\s*[;){]))", 1235 | "name": "invalid.illegal.comma.css" 1236 | }, 1237 | { 1238 | "include": "#commas" 1239 | }, 1240 | { 1241 | "begin": "\\(", 1242 | "beginCaptures": { 1243 | "0": { 1244 | "name": "punctuation.definition.parameters.begin.bracket.round.css" 1245 | } 1246 | }, 1247 | "end": "\\)", 1248 | "endCaptures": { 1249 | "0": { 1250 | "name": "punctuation.definition.parameters.end.bracket.round.css" 1251 | } 1252 | }, 1253 | "patterns": [ 1254 | { 1255 | "include": "#media-features" 1256 | }, 1257 | { 1258 | "include": "#media-feature-keywords" 1259 | }, 1260 | { 1261 | "match": ":", 1262 | "name": "punctuation.separator.key-value.css" 1263 | }, 1264 | { 1265 | "match": ">=|<=|=|<|>", 1266 | "name": "keyword.operator.comparison.css" 1267 | }, 1268 | { 1269 | "captures": { 1270 | "1": { 1271 | "name": "constant.numeric.css" 1272 | }, 1273 | "2": { 1274 | "name": "keyword.operator.arithmetic.css" 1275 | }, 1276 | "3": { 1277 | "name": "constant.numeric.css" 1278 | } 1279 | }, 1280 | "match": "(\\d+)\\s*(/)\\s*(\\d+)", 1281 | "name": "meta.ratio.css" 1282 | }, 1283 | { 1284 | "include": "#numeric-values" 1285 | }, 1286 | { 1287 | "include": "#comment-block" 1288 | } 1289 | ] 1290 | } 1291 | ] 1292 | }, 1293 | "media-query-list": { 1294 | "begin": "(?=\\s*[^{;])", 1295 | "end": "(?=\\s*[{;])", 1296 | "patterns": [ 1297 | { 1298 | "include": "#media-query" 1299 | } 1300 | ] 1301 | }, 1302 | "media-types": { 1303 | "captures": { 1304 | "1": { 1305 | "name": "support.constant.media.css" 1306 | }, 1307 | "2": { 1308 | "name": "invalid.deprecated.constant.media.css" 1309 | } 1310 | }, 1311 | "match": "(?xi)\n(?<=^|\\s|,|\\*/)\n(?:\n # Valid media types\n (all|print|screen|speech)\n |\n # Deprecated in Media Queries 4: http://dev.w3.org/csswg/mediaqueries/#media-types\n (aural|braille|embossed|handheld|projection|tty|tv)\n)\n(?=$|[{,\\s;]|/\\*)" 1312 | }, 1313 | "numeric-values": { 1314 | "patterns": [ 1315 | { 1316 | "captures": { 1317 | "1": { 1318 | "name": "punctuation.definition.constant.css" 1319 | } 1320 | }, 1321 | "match": "(#)(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\\b", 1322 | "name": "constant.other.color.rgb-value.hex.css" 1323 | }, 1324 | { 1325 | "captures": { 1326 | "1": { 1327 | "name": "keyword.other.unit.percentage.css" 1328 | }, 1329 | "2": { 1330 | "name": "keyword.other.unit.${2:/downcase}.css" 1331 | } 1332 | }, 1333 | "match": "(?xi) (?+~|] # - Followed by another selector\n | /\\* # - Followed by a block comment\n )\n |\n # Name contains unescaped ASCII symbol\n (?: # Check for acceptable preceding characters\n [-a-zA-Z_0-9]|[^\\x00-\\x7F] # - Valid selector character\n | \\\\(?:[0-9a-fA-F]{1,6}|.) # - Escape sequence\n )*\n (?: # Invalid punctuation\n [!\"'%&(*;+~|] # - Another selector\n | /\\* # - A block comment\n)", 1575 | "name": "entity.other.attribute-name.class.css" 1576 | }, 1577 | { 1578 | "captures": { 1579 | "1": { 1580 | "name": "punctuation.definition.entity.css" 1581 | }, 1582 | "2": { 1583 | "patterns": [ 1584 | { 1585 | "include": "#escapes" 1586 | } 1587 | ] 1588 | } 1589 | }, 1590 | "match": "(?x)\n(\\#)\n(\n -?\n (?![0-9])\n (?:[-a-zA-Z0-9_]|[^\\x00-\\x7F]|\\\\(?:[0-9a-fA-F]{1,6}|.))+\n)\n(?=$|[\\s,.\\#)\\[:{>+~|]|/\\*)", 1591 | "name": "entity.other.attribute-name.id.css" 1592 | }, 1593 | { 1594 | "begin": "\\[", 1595 | "beginCaptures": { 1596 | "0": { 1597 | "name": "punctuation.definition.entity.begin.bracket.square.css" 1598 | } 1599 | }, 1600 | "end": "\\]", 1601 | "endCaptures": { 1602 | "0": { 1603 | "name": "punctuation.definition.entity.end.bracket.square.css" 1604 | } 1605 | }, 1606 | "name": "meta.attribute-selector.css", 1607 | "patterns": [ 1608 | { 1609 | "include": "#comment-block" 1610 | }, 1611 | { 1612 | "include": "#string" 1613 | }, 1614 | { 1615 | "captures": { 1616 | "1": { 1617 | "name": "storage.modifier.ignore-case.css" 1618 | } 1619 | }, 1620 | "match": "(?<=[\"'\\s]|^|\\*/)\\s*([iI])\\s*(?=[\\s\\]]|/\\*|$)" 1621 | }, 1622 | { 1623 | "captures": { 1624 | "1": { 1625 | "name": "string.unquoted.attribute-value.css", 1626 | "patterns": [ 1627 | { 1628 | "include": "#escapes" 1629 | } 1630 | ] 1631 | } 1632 | }, 1633 | "match": "(?x)(?<==)\\s*((?!/\\*)(?:[^\\\\\"'\\s\\]]|\\\\.)+)" 1634 | }, 1635 | { 1636 | "include": "#escapes" 1637 | }, 1638 | { 1639 | "match": "[~|^$*]?=", 1640 | "name": "keyword.operator.pattern.css" 1641 | }, 1642 | { 1643 | "match": "\\|", 1644 | "name": "punctuation.separator.css" 1645 | }, 1646 | { 1647 | "captures": { 1648 | "1": { 1649 | "name": "entity.other.namespace-prefix.css", 1650 | "patterns": [ 1651 | { 1652 | "include": "#escapes" 1653 | } 1654 | ] 1655 | } 1656 | }, 1657 | "match": "(?x)\n# Qualified namespace prefix\n( -?(?!\\d)(?:[\\w-]|[^\\x00-\\x7F]|\\\\(?:[0-9a-fA-F]{1,6}|.))+\n| \\*\n)\n# Lookahead to ensure there's a valid identifier ahead\n(?=\n \\| (?!\\s|=|$|\\])\n (?: -?(?!\\d)\n | [\\\\\\w-]\n | [^\\x00-\\x7F]\n )\n)" 1658 | }, 1659 | { 1660 | "captures": { 1661 | "1": { 1662 | "name": "entity.other.attribute-name.css", 1663 | "patterns": [ 1664 | { 1665 | "include": "#escapes" 1666 | } 1667 | ] 1668 | } 1669 | }, 1670 | "match": "(?x)\n(-?(?!\\d)(?>[\\w-]|[^\\x00-\\x7F]|\\\\(?:[0-9a-fA-F]{1,6}|.))+)\n\\s*\n(?=[~|^\\]$*=]|/\\*)" 1671 | } 1672 | ] 1673 | }, 1674 | { 1675 | "include": "#pseudo-classes" 1676 | }, 1677 | { 1678 | "include": "#pseudo-elements" 1679 | }, 1680 | { 1681 | "include": "#functional-pseudo-classes" 1682 | }, 1683 | { 1684 | "match": "(?x) (?\\s,.\\#|){:\\[]|/\\*|$)", 1755 | "name": "entity.name.tag.css" 1756 | }, 1757 | "unicode-range": { 1758 | "captures": { 1759 | "0": { 1760 | "name": "constant.other.unicode-range.css" 1761 | }, 1762 | "1": { 1763 | "name": "punctuation.separator.dash.unicode-range.css" 1764 | } 1765 | }, 1766 | "match": "(?]*>)", 24 | "beginCaptures": { 25 | "1": { 26 | "name": "punctuation.definition.tag.html" 27 | }, 28 | "2": { 29 | "name": "entity.name.tag.html" 30 | } 31 | }, 32 | "end": "(>(<)/)(\\2)(>)", 33 | "endCaptures": { 34 | "1": { 35 | "name": "punctuation.definition.tag.html" 36 | }, 37 | "2": { 38 | "name": "meta.scope.between-tag-pair.html" 39 | }, 40 | "3": { 41 | "name": "entity.name.tag.html" 42 | }, 43 | "4": { 44 | "name": "punctuation.definition.tag.html" 45 | } 46 | }, 47 | "name": "meta.tag.any.html", 48 | "patterns": [ 49 | { 50 | "include": "#tag-stuff" 51 | } 52 | ] 53 | }, 54 | { 55 | "begin": "(<\\?)(xml)", 56 | "captures": { 57 | "1": { 58 | "name": "punctuation.definition.tag.html" 59 | }, 60 | "2": { 61 | "name": "entity.name.tag.xml.html" 62 | } 63 | }, 64 | "end": "(\\?>)", 65 | "name": "meta.tag.preprocessor.xml.html", 66 | "patterns": [ 67 | { 68 | "include": "#tag-generic-attribute" 69 | }, 70 | { 71 | "include": "#string-double-quoted" 72 | }, 73 | { 74 | "include": "#string-single-quoted" 75 | } 76 | ] 77 | }, 78 | { 79 | "begin": "