├── .gitignore ├── binding.gyp ├── bindings ├── node │ ├── index.js │ └── binding.cc └── rust │ ├── build.rs │ └── lib.rs ├── Cargo.toml ├── .github └── workflows │ ├── pr-test.yml │ └── release.yml ├── package.json ├── src ├── scanner │ └── LICENSE ├── scanner.c ├── tree_sitter │ └── parser.h ├── node-types.json └── grammar.json ├── LICENSE ├── corpus ├── formats.txt └── interpolation.txt ├── grammar.js ├── README.md └── css-in-js-mode.el /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | target 4 | *.log 5 | Cargo.lock 6 | tree-sitter-css -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_css_in_js_binding", 5 | "include_dirs": [ 6 | " 3 | #include "nan.h" 4 | 5 | using namespace v8; 6 | 7 | extern "C" TSLanguage * tree_sitter_css_in_js(); 8 | 9 | namespace { 10 | 11 | NAN_METHOD(New) {} 12 | 13 | void Init(Local exports, Local module) { 14 | Local tpl = Nan::New(New); 15 | tpl->SetClassName(Nan::New("Language").ToLocalChecked()); 16 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 17 | 18 | Local constructor = Nan::GetFunction(tpl).ToLocalChecked(); 19 | Local instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked(); 20 | Nan::SetInternalFieldPointer(instance, 0, tree_sitter_css_in_js()); 21 | 22 | Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("css_in_js").ToLocalChecked()); 23 | Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance); 24 | } 25 | 26 | NODE_MODULE(tree_sitter_css_in_js_binding, Init) 27 | 28 | } // namespace 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-css-in-js", 3 | "version": "0.0.1", 4 | "description": "css-in-js grammar for tree-sitter", 5 | "main": "bindings/node", 6 | "keywords": [ 7 | "parsing", 8 | "incremental" 9 | ], 10 | "dependencies": { 11 | "nan": "^2.18.0", 12 | "node-gyp": "^10.0.1" 13 | }, 14 | "devDependencies": { 15 | "tree-sitter-cli": "^0.20.8" 16 | }, 17 | "scripts": { 18 | "build": "node-gyp configure && node-gyp build && tree-sitter generate", 19 | "clone": "git clone https://github.com/tree-sitter/tree-sitter-css.git", 20 | "go": "node-gyp configure && node-gyp build && tree-sitter generate && tree-sitter test", 21 | "postinstall": "npm run clone", 22 | "test": "tree-sitter test" 23 | }, 24 | "tree-sitter": [ 25 | { 26 | "scope": "source.css", 27 | "file-types": [ 28 | "css" 29 | ], 30 | "injection-regex": "^css_in_js$" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /src/scanner/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Max Brunsfeld 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 all 13 | 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 THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Dan Orzechowski 4 | src/scanner.c Copyright (c) 2018 Max Brunsfeld 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /bindings/rust/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let src_dir = std::path::Path::new("src"); 3 | 4 | let mut c_config = cc::Build::new(); 5 | c_config.include(&src_dir); 6 | c_config 7 | .flag_if_supported("-Wno-unused-parameter") 8 | .flag_if_supported("-Wno-unused-but-set-variable") 9 | .flag_if_supported("-Wno-trigraphs"); 10 | let parser_path = src_dir.join("parser.c"); 11 | c_config.file(&parser_path); 12 | 13 | // If your language uses an external scanner written in C, 14 | // then include this block of code: 15 | 16 | /* 17 | let scanner_path = src_dir.join("scanner.c"); 18 | c_config.file(&scanner_path); 19 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 20 | */ 21 | 22 | c_config.compile("parser"); 23 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); 24 | 25 | // If your language uses an external scanner written in C++, 26 | // then include this block of code: 27 | 28 | /* 29 | let mut cpp_config = cc::Build::new(); 30 | cpp_config.cpp(true); 31 | cpp_config.include(&src_dir); 32 | cpp_config 33 | .flag_if_supported("-Wno-unused-parameter") 34 | .flag_if_supported("-Wno-unused-but-set-variable"); 35 | let scanner_path = src_dir.join("scanner.cc"); 36 | cpp_config.file(&scanner_path); 37 | cpp_config.compile("scanner"); 38 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 39 | */ 40 | } 41 | -------------------------------------------------------------------------------- /src/scanner.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | enum TokenType { 5 | DESCENDANT_OP, 6 | }; 7 | 8 | void *tree_sitter_css_in_js_external_scanner_create() { return NULL; } 9 | void tree_sitter_css_in_js_external_scanner_destroy(void *p) {} 10 | void tree_sitter_css_in_js_external_scanner_reset(void *p) {} 11 | unsigned tree_sitter_css_in_js_external_scanner_serialize(void *p, char *buffer) { return 0; } 12 | void tree_sitter_css_in_js_external_scanner_deserialize(void *p, const char *b, unsigned n) {} 13 | 14 | bool tree_sitter_css_in_js_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { 15 | if (iswspace(lexer->lookahead) && valid_symbols[DESCENDANT_OP]) { 16 | lexer->result_symbol = DESCENDANT_OP; 17 | 18 | lexer->advance(lexer, true); 19 | while (iswspace(lexer->lookahead)) { 20 | lexer->advance(lexer, true); 21 | } 22 | lexer->mark_end(lexer); 23 | 24 | if ( 25 | lexer->lookahead == '#' || 26 | lexer->lookahead == '.' || 27 | lexer->lookahead == '[' || 28 | lexer->lookahead == '-' || 29 | iswalnum(lexer->lookahead) 30 | ) { 31 | return true; 32 | } 33 | 34 | if (lexer->lookahead == ':') { 35 | lexer->advance(lexer, false); 36 | if (iswspace(lexer->lookahead)) return false; 37 | for (;;) { 38 | if ( 39 | lexer->lookahead == ';' || 40 | lexer->lookahead == '}' || 41 | lexer->eof(lexer) 42 | ) return false; 43 | if (lexer->lookahead == '{') { 44 | return true; 45 | } 46 | lexer->advance(lexer, false); 47 | } 48 | } 49 | } 50 | 51 | return false; 52 | } 53 | -------------------------------------------------------------------------------- /corpus/formats.txt: -------------------------------------------------------------------------------- 1 | ==================== 2 | identifier 3 | ==================== 4 | 5 | ${foo} 6 | 7 | --- 8 | 9 | (stylesheet 10 | (js_interpolation)) 11 | 12 | ==================== 13 | dot-notation property access 14 | ==================== 15 | 16 | ${foo.bar} 17 | ${foo?.bar} 18 | 19 | --- 20 | 21 | (stylesheet 22 | (js_interpolation) 23 | (js_interpolation)) 24 | 25 | ==================== 26 | bracket-notation property access 27 | ==================== 28 | 29 | ${foo[bar]} 30 | ${foo['bar']} 31 | 32 | --- 33 | 34 | (stylesheet 35 | (js_interpolation) 36 | (js_interpolation)) 37 | 38 | ==================== 39 | function invocation 40 | ==================== 41 | 42 | ${foo(bar)} 43 | ${foo("bar", 1, true)} 44 | 45 | --- 46 | 47 | (stylesheet 48 | (js_interpolation) 49 | (js_interpolation)) 50 | 51 | ==================== 52 | null coalescing 53 | ==================== 54 | 55 | ${foo ?? bar.baz} 56 | 57 | --- 58 | 59 | (stylesheet 60 | (js_interpolation)) 61 | 62 | ==================== 63 | ternary 64 | ==================== 65 | 66 | ${foo ? bar.baz : 'auto'} 67 | 68 | --- 69 | 70 | (stylesheet 71 | (js_interpolation)) 72 | 73 | ==================== 74 | fat-arrow function, 1 parameter, no parens 75 | ==================== 76 | 77 | ${foo => foo.bar} 78 | 79 | --- 80 | 81 | (stylesheet 82 | (js_interpolation)) 83 | 84 | ==================== 85 | fat-arrow function, 1 parameter, parens 86 | ==================== 87 | 88 | ${(foo) => foo.bar} 89 | 90 | --- 91 | 92 | (stylesheet 93 | (js_interpolation)) 94 | 95 | ==================== 96 | fat-arrow function, 1 parameter, 1 destructured parameter 97 | ==================== 98 | 99 | ${({foo}) => foo} 100 | 101 | --- 102 | 103 | (stylesheet 104 | (js_interpolation)) 105 | -------------------------------------------------------------------------------- /corpus/interpolation.txt: -------------------------------------------------------------------------------- 1 | ==================== 2 | bare interpolation 3 | ==================== 4 | 5 | ${foo} 6 | 7 | --- 8 | 9 | (stylesheet 10 | (js_interpolation)) 11 | 12 | ==================== 13 | interpolation as rule 14 | ==================== 15 | 16 | * { 17 | ${foo} 18 | } 19 | 20 | --- 21 | 22 | (stylesheet 23 | (rule_set 24 | (selectors 25 | (universal_selector)) 26 | (block 27 | (js_interpolation)))) 28 | 29 | ==================== 30 | interpolation as rule value 31 | ==================== 32 | 33 | * { 34 | height: ${foo}; 35 | } 36 | 37 | --- 38 | 39 | (stylesheet 40 | (rule_set 41 | (selectors 42 | (universal_selector)) 43 | (block 44 | (declaration 45 | (property_name) (js_interpolation))))) 46 | 47 | ==================== 48 | interpolation before rule block 49 | ==================== 50 | 51 | ${foo} 52 | 53 | * { 54 | height: 0; 55 | } 56 | 57 | --- 58 | 59 | (stylesheet 60 | (js_interpolation) 61 | (rule_set 62 | (selectors 63 | (universal_selector)) 64 | (block 65 | (declaration 66 | (property_name) (integer_value))))) 67 | 68 | ==================== 69 | interpolation after rule block 70 | ==================== 71 | 72 | * { 73 | height: 0; 74 | } 75 | 76 | ${foo} 77 | 78 | --- 79 | 80 | (stylesheet 81 | (rule_set 82 | (selectors 83 | (universal_selector)) 84 | (block 85 | (declaration 86 | (property_name) (integer_value)))) 87 | (js_interpolation)) 88 | 89 | ==================== 90 | interpolation inside a block 91 | ==================== 92 | 93 | div { 94 | ${foo}; 95 | } 96 | 97 | --- 98 | 99 | (stylesheet 100 | (rule_set 101 | (selectors 102 | (tag_name)) 103 | (block 104 | (js_interpolation)))) 105 | 106 | ==================== 107 | interpolation with other rules 108 | ==================== 109 | 110 | ${foo}; 111 | display: block; 112 | 113 | --- 114 | 115 | (stylesheet 116 | (js_interpolation) 117 | (declaration 118 | (property_name) 119 | (plain_value))) 120 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides css_in_js language support for the [tree-sitter][] parsing library. 2 | //! 3 | //! Typically, you will use the [language][language func] function to add this language to a 4 | //! tree-sitter [Parser][], and then use the parser to parse some code: 5 | //! 6 | //! ``` 7 | //! let code = ""; 8 | //! let mut parser = tree_sitter::Parser::new(); 9 | //! parser.set_language(tree_sitter_css_in_js::language()).expect("Error loading css_in_js grammar"); 10 | //! let tree = parser.parse(code, None).unwrap(); 11 | //! ``` 12 | //! 13 | //! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html 14 | //! [language func]: fn.language.html 15 | //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html 16 | //! [tree-sitter]: https://tree-sitter.github.io/ 17 | 18 | use tree_sitter::Language; 19 | 20 | extern "C" { 21 | fn tree_sitter_css_in_js() -> Language; 22 | } 23 | 24 | /// Get the tree-sitter [Language][] for this grammar. 25 | /// 26 | /// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html 27 | pub fn language() -> Language { 28 | unsafe { tree_sitter_css_in_js() } 29 | } 30 | 31 | /// The content of the [`node-types.json`][] file for this grammar. 32 | /// 33 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types 34 | pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json"); 35 | 36 | // Uncomment these to include any queries that this grammar contains 37 | 38 | // pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm"); 39 | // pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm"); 40 | // pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm"); 41 | // pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm"); 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | #[test] 46 | fn test_can_load_grammar() { 47 | let mut parser = tree_sitter::Parser::new(); 48 | parser 49 | .set_language(super::language()) 50 | .expect("Error loading css_in_js language"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | /*** 2 | * this is not intended to be a full-blown JS parser bolted onto the side of the 3 | * CSS parser. it's an attempt to tokenize the most common contents of JS 4 | * string-template substitutions used in CSS-in-JS contexts. complex JS 5 | * expressions will probably cause this parser to fail, but you shouldn't be 6 | * using complex JS expressions in your CSS-in-JS anyway. 7 | ***/ 8 | 9 | module.exports = grammar(require('./tree-sitter-css/grammar'), { 10 | name: 'css_in_js', 11 | 12 | rules: { 13 | /* new rules specific to CSS-in-JS */ 14 | 15 | _js_identifier: $ => /[$_a-zA-Z0-9]+/, 16 | 17 | _js_string: $ => token(choice( 18 | seq("'", /([^'\n]|\\(.|\n))*/, "'"), 19 | seq('"', /([^"\n]|\\(.|\n))*/, '"'), 20 | seq('`', /([^`\n]|\\(.|\n))*/, '`') 21 | )), 22 | 23 | _js_expr: $ => choice( 24 | $._js_string, 25 | prec.right(1, seq($._js_expr, /\+\-\*\/%/, $._js_expr)), // foo + bar 26 | prec.right(1, seq($._js_expr, '??', $._js_expr)), // foo ?? bar 27 | prec.right(0, seq($._js_expr, '?', $._js_expr, ':', $._js_expr)), // foo ? bar : baz 28 | seq( 29 | $._js_identifier, 30 | optional(choice( 31 | seq(/\??\./, $._js_identifier), // foo?.bar 32 | seq(optional(/\??\./), '(', optional($._js_args), ')'), // foo?.(bar) 33 | seq(optional(/\??\./), '[', $._js_expr, ']') // foo?.[bar] 34 | )) 35 | ) 36 | ), 37 | 38 | _js_param: $ => choice( 39 | $._js_identifier, 40 | seq('{', $._js_params, '}') 41 | ), 42 | 43 | _js_params: $ => seq( 44 | $._js_param, 45 | repeat(seq(',', $._js_param)) 46 | ), 47 | 48 | _js_args: $ => seq( 49 | $._js_expr, 50 | repeat(seq( 51 | ',', 52 | $._js_expr 53 | )) 54 | ), 55 | 56 | _js_fat_arrow_function: $ => seq( 57 | choice( 58 | $._js_identifier, 59 | seq('(', optional($._js_params), ')') 60 | ), 61 | '=>', 62 | $._js_expr 63 | ), 64 | 65 | js_interpolation: $ => seq( 66 | '${', 67 | choice( 68 | $._js_expr, 69 | $._js_fat_arrow_function 70 | ), 71 | '}' 72 | ), 73 | 74 | /* re-exports of CSS grammar rules so we can reference them */ 75 | 76 | identifier: ($, original) => original, 77 | _value: ($, original) => original, 78 | important: ($, original) => original, 79 | 80 | /* updates to original CSS grammar rules */ 81 | 82 | _top_level_item: ($, original) => choice( 83 | original, 84 | $._block_item, 85 | $.js_interpolation 86 | ), 87 | 88 | _block_item: ($, original) => choice( 89 | original, 90 | seq($.js_interpolation, optional(';')) 91 | ), 92 | 93 | declaration: ($, original) => choice( 94 | original, 95 | seq( 96 | alias($.identifier, $.property_name), // keep alias from CSS rule 97 | ':', 98 | $.js_interpolation, 99 | repeat(seq( 100 | optional(','), 101 | $._value 102 | )), 103 | optional($.important), 104 | ';' 105 | ) 106 | ) 107 | } 108 | }); 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-css-in-js 2 | 3 | ## tree-sitter grammar 4 | 5 | a [tree-sitter](https://tree-sitter.github.io/tree-sitter/) grammar based on [the existing CSS tree-sitter grammar](https://github.com/tree-sitter/tree-sitter-css) which adds support for Javascript/Typescript template-string interpolation tokens. the intended usage is in IDEs where source code files are parsed using multiple tree-sitter languages at the same time: 6 | 7 | ``` 8 | const height = '16px'; /* javascript */ 9 | const MyComponent = styled.div` 10 | display: inline-block; /* CSS */ 11 | height: ${height}; /* both! */ 12 | background-color: tomato; 13 | `; 14 | ``` 15 | 16 | this should provide the basic functionality required for IDEs to support features like indentation, syntax highlighting, and code-completion hinting for CSS-in-JS using tree-sitter: 17 | 18 | ![](https://repository-images.githubusercontent.com/515372828/a6f10257-e841-4553-9ccf-b7e6cd525b18) 19 | 20 | ### Releases 21 | 22 | shared libraries for all supported OS+CPU platforms are automatically built for you. Freshest copies of these shared libraries can be found in the Github release tagged `latest`. 23 | 24 | | OS | Arch | Status | 25 | |---------|---------|------------------| 26 | | Linux | x86\_64 | builds; tested | 27 | | OSX | x86\_64 | builds; untested | 28 | | OSX | arm64 | builds; tested | 29 | | Windows | x86\_64 | builds; untested | 30 | 31 | ### Local build instructions 32 | 33 | 1. clone this repo 34 | 2. run `npm install` to install dependencies 35 | 3. run `npm run build` to build a tree-sitter shared library appropriate for your platform. the shared library will be written to a platform-specific directory; check [tree-sitter's documentation](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#per-user-configuration) to see where your .so / .dll is. 36 | 37 | emacs users should note that this repository is not currently compatible with the language-builder repo at https://github.com/casouri/tree-sitter-module/ . (the package.json in this repo has an npm postinstall step which clones the base CSS grammar repo) 38 | 39 | ## emacs minor mode 40 | 41 | `css-in-js-mode` is an emacs minor mode designed to bring support for (several flavors of) CSS-in-JS to the treesit-aware Javascript/Typescript/JSX/TSX major modes in emacs version 29.0 and newer. syntax highlighting, indentation, and completion-at-point are all supported. 42 | 43 | ### Requirements 44 | 45 | - a version of emacs compiled with treesit support 46 | 47 | ### Installation 48 | 49 | 1. download `css-in-js-mode.el` and put it in a directory listed in your `load-path` 50 | 1. load the file: `(require 'css-in-js-mode)` 51 | 52 | > these steps can also be done using [straight.el](https://github.com/radian-software/straight.el): 53 | > `(straight-use-package '(css-in-js-mode :type git :host github :repo "orzechowskid/tree-sitter-css-in-js"))` 54 | > 55 | > or using straight.el plus use-package: 56 | > `(use-package css-in-js-mode 57 | > :straight '(css-in-js-mode :type git :host github :repo "orzechowskid/tree-sitter-css-in-js"))` 58 | 59 | ### Usage 60 | 61 | 1. fetch the tree-sitter shared library appropriate for your OS+CPU if you don't already have it on disk: `(css-in-js-mode-fetch-shared-library)` (and pass it an argument of `t` to force a re-download of the latest released version if you do already have it on disk) 62 | 1. visit a javascript/typescript file and enable the Typescript[TSX] major mode: `(tsx-ts-mode)` 63 | 1. enable this minor-mode: `(css-in-js-mode)` 64 | 65 | ### Configuration 66 | 67 | useful variables are members of the `css-in-js-mode` customization group and can be viewed and modified with the command `M-x customize-group [RET] css-in-js-mode [RET]`. 68 | 69 | this minor mode also uses `css-indent-offset` to control the amount of whitespace applied to each indent step so be sure to set that to an acceptable value too. 70 | 71 | ## Bugs 72 | 73 | ### Grammar bugs 74 | 75 | please first check to see that your bug is not present when parsing a file using the base CSS grammar (from which the CSS-in-JS grammar derives). if it is present there too then you'll want to file an issue over at https://github.com/tree-sitter/tree-sitter-css . 76 | 77 | ### emacs minor-mode bugs 78 | 79 | please first check to see that your bug is not present in the base `tsx-ts-mode` or `css-ts-mode` (whichever one is applicable). if it is present there too then you'll want to file an issue against emacs by using `M-x report-emacs-bug` (after reading through the manual at `M-x info-emacs-bug` first). 80 | 81 | ## License 82 | 83 | src/scanner.c is © 2018 Max Brunsfeld, licensed under the MIT License. Original source can be found at https://github.com/tree-sitter/tree-sitter-css . 84 | all other code is licensed under the MIT License. See LICENSE in the top level of this repository. 85 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Auto-release 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | paths: 11 | - grammar.js 12 | - src/**/* 13 | - corpus/**/* 14 | 15 | jobs: 16 | build-release-linux: 17 | runs-on: ubuntu-latest 18 | 19 | permissions: 20 | contents: write 21 | 22 | steps: 23 | - name: Get Node.js ${{ matrix.node-version }} 24 | uses: actions/checkout@v3 25 | 26 | - name: Use Node.js ${{ matrix.node-version }} 27 | uses: actions/setup-node@v3 28 | with: 29 | node-version: ${{ matrix.node-version }} 30 | cache: 'npm' 31 | 32 | - name: Build and test 33 | run: | 34 | npm ci 35 | npm run build --if-present 36 | npm run test 37 | mv /home/runner/.cache/tree-sitter/lib/css_in_js.so /home/runner/.cache/tree-sitter/lib/libtree-sitter-css-in-js.so 38 | 39 | - name: Create tar file 40 | uses: TheDoctor0/zip-release@0.6.2 41 | with: 42 | type: tar 43 | directory: /home/runner/.cache/tree-sitter/lib 44 | path: libtree-sitter-css-in-js.so 45 | filename: linux.tar.gz 46 | 47 | - name: Upload tarball 48 | uses: actions/upload-artifact@v3 49 | with: 50 | name: linux-latest 51 | path: /home/runner/.cache/tree-sitter/lib/linux.tar.gz 52 | if-no-files-found: error 53 | retention-days: 1 54 | 55 | 56 | build-release-windows: 57 | runs-on: windows-latest 58 | 59 | permissions: 60 | contents: write 61 | 62 | steps: 63 | 64 | - name: Get Node.js ${{ matrix.node-version }} 65 | uses: actions/checkout@v3 66 | 67 | - name: Use Node.js ${{ matrix.node-version }} 68 | uses: actions/setup-node@v3 69 | with: 70 | node-version: ${{ matrix.node-version }} 71 | cache: 'npm' 72 | 73 | - name: Build and test 74 | run: | 75 | npm ci 76 | npm run build --if-present 77 | npm run test 78 | copy C:\Users\runneradmin\AppData\Local\tree-sitter\lib\css_in_js.dll C:\Users\runneradmin\AppData\Local\tree-sitter\lib\libtree-sitter-css-in-js.dll 79 | 80 | - name: Create tar file 81 | uses: TheDoctor0/zip-release@0.6.2 82 | with: 83 | type: tar 84 | directory: C:\Users\runneradmin\AppData\Local\tree-sitter\lib 85 | path: libtree-sitter-css-in-js.dll 86 | filename: windows.tar.gz 87 | 88 | - name: Upload tarball 89 | uses: actions/upload-artifact@v3 90 | with: 91 | name: windows-latest 92 | path: C:\Users\runneradmin\AppData\Local\tree-sitter\lib\windows.tar.gz 93 | if-no-files-found: error 94 | retention-days: 1 95 | 96 | 97 | build-release-macos: 98 | runs-on: macos-latest 99 | 100 | permissions: 101 | contents: write 102 | 103 | steps: 104 | 105 | - name: Get Node.js ${{ matrix.node-version }} 106 | uses: actions/checkout@v3 107 | 108 | - name: Use Node.js ${{ matrix.node-version }} 109 | uses: actions/setup-node@v3 110 | with: 111 | node-version: ${{ matrix.node-version }} 112 | cache: 'npm' 113 | 114 | - name: Build and test 115 | run: | 116 | npm ci 117 | npm run build --if-present 118 | npm run test 119 | mv /Users/runner/Library/Caches/tree-sitter/lib/css_in_js.so /Users/runner/Library/Caches/tree-sitter/lib/libtree-sitter-css-in-js.so 120 | # arm64 121 | gcc -fPIC -c -I./src src/parser.c src/scanner.c -target arm64-apple-macos11 122 | cc -fPIC -shared parser.o scanner.o -o "libtree-sitter-css-in-js.dylib" -target arm64-apple-macos11 123 | mv libtree-sitter-css-in-js.dylib /Users/runner/Library/Caches/tree-sitter/lib 124 | 125 | - name: Create tar file 126 | uses: TheDoctor0/zip-release@0.6.2 127 | with: 128 | type: tar 129 | directory: /Users/runner/Library/Caches/tree-sitter/lib 130 | path: libtree-sitter-css-in-js.* 131 | filename: macos.tar.gz 132 | 133 | - name: Upload tarball 134 | uses: actions/upload-artifact@v3 135 | with: 136 | name: macos-latest 137 | path: /Users/runner/Library/Caches/tree-sitter/lib/macos.tar.gz 138 | if-no-files-found: error 139 | retention-days: 1 140 | 141 | 142 | generate-release: 143 | runs-on: ubuntu-latest 144 | 145 | needs: [ build-release-macos, build-release-windows, build-release-linux ] 146 | #needs: [ build-release-linux ] 147 | permissions: 148 | contents: write 149 | 150 | steps: 151 | 152 | - name: Collect tarballs 153 | uses: actions/download-artifact@v3 154 | with: 155 | path: ./artifacts 156 | - name: Publish release 157 | uses: "marvinpinto/action-automatic-releases@latest" 158 | with: 159 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 160 | automatic_release_tag: "latest" 161 | prerelease: false 162 | title: "Grammar binaries bundle" 163 | files: | 164 | artifacts/linux-latest/linux.tar.gz 165 | artifacts/windows-latest/windows.tar.gz 166 | artifacts/macos-latest/macos.tar.gz 167 | -------------------------------------------------------------------------------- /src/tree_sitter/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_PARSER_H_ 2 | #define TREE_SITTER_PARSER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define ts_builtin_sym_error ((TSSymbol)-1) 13 | #define ts_builtin_sym_end 0 14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 | 16 | typedef uint16_t TSStateId; 17 | 18 | #ifndef TREE_SITTER_API_H_ 19 | typedef uint16_t TSSymbol; 20 | typedef uint16_t TSFieldId; 21 | typedef struct TSLanguage TSLanguage; 22 | #endif 23 | 24 | typedef struct { 25 | TSFieldId field_id; 26 | uint8_t child_index; 27 | bool inherited; 28 | } TSFieldMapEntry; 29 | 30 | typedef struct { 31 | uint16_t index; 32 | uint16_t length; 33 | } TSFieldMapSlice; 34 | 35 | typedef struct { 36 | bool visible; 37 | bool named; 38 | bool supertype; 39 | } TSSymbolMetadata; 40 | 41 | typedef struct TSLexer TSLexer; 42 | 43 | struct TSLexer { 44 | int32_t lookahead; 45 | TSSymbol result_symbol; 46 | void (*advance)(TSLexer *, bool); 47 | void (*mark_end)(TSLexer *); 48 | uint32_t (*get_column)(TSLexer *); 49 | bool (*is_at_included_range_start)(const TSLexer *); 50 | bool (*eof)(const TSLexer *); 51 | }; 52 | 53 | typedef enum { 54 | TSParseActionTypeShift, 55 | TSParseActionTypeReduce, 56 | TSParseActionTypeAccept, 57 | TSParseActionTypeRecover, 58 | } TSParseActionType; 59 | 60 | typedef union { 61 | struct { 62 | uint8_t type; 63 | TSStateId state; 64 | bool extra; 65 | bool repetition; 66 | } shift; 67 | struct { 68 | uint8_t type; 69 | uint8_t child_count; 70 | TSSymbol symbol; 71 | int16_t dynamic_precedence; 72 | uint16_t production_id; 73 | } reduce; 74 | uint8_t type; 75 | } TSParseAction; 76 | 77 | typedef struct { 78 | uint16_t lex_state; 79 | uint16_t external_lex_state; 80 | } TSLexMode; 81 | 82 | typedef union { 83 | TSParseAction action; 84 | struct { 85 | uint8_t count; 86 | bool reusable; 87 | } entry; 88 | } TSParseActionEntry; 89 | 90 | struct TSLanguage { 91 | uint32_t version; 92 | uint32_t symbol_count; 93 | uint32_t alias_count; 94 | uint32_t token_count; 95 | uint32_t external_token_count; 96 | uint32_t state_count; 97 | uint32_t large_state_count; 98 | uint32_t production_id_count; 99 | uint32_t field_count; 100 | uint16_t max_alias_sequence_length; 101 | const uint16_t *parse_table; 102 | const uint16_t *small_parse_table; 103 | const uint32_t *small_parse_table_map; 104 | const TSParseActionEntry *parse_actions; 105 | const char * const *symbol_names; 106 | const char * const *field_names; 107 | const TSFieldMapSlice *field_map_slices; 108 | const TSFieldMapEntry *field_map_entries; 109 | const TSSymbolMetadata *symbol_metadata; 110 | const TSSymbol *public_symbol_map; 111 | const uint16_t *alias_map; 112 | const TSSymbol *alias_sequences; 113 | const TSLexMode *lex_modes; 114 | bool (*lex_fn)(TSLexer *, TSStateId); 115 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 116 | TSSymbol keyword_capture_token; 117 | struct { 118 | const bool *states; 119 | const TSSymbol *symbol_map; 120 | void *(*create)(void); 121 | void (*destroy)(void *); 122 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 123 | unsigned (*serialize)(void *, char *); 124 | void (*deserialize)(void *, const char *, unsigned); 125 | } external_scanner; 126 | const TSStateId *primary_state_ids; 127 | }; 128 | 129 | /* 130 | * Lexer Macros 131 | */ 132 | 133 | #define START_LEXER() \ 134 | bool result = false; \ 135 | bool skip = false; \ 136 | bool eof = false; \ 137 | int32_t lookahead; \ 138 | goto start; \ 139 | next_state: \ 140 | lexer->advance(lexer, skip); \ 141 | start: \ 142 | skip = false; \ 143 | lookahead = lexer->lookahead; 144 | 145 | #define ADVANCE(state_value) \ 146 | { \ 147 | state = state_value; \ 148 | goto next_state; \ 149 | } 150 | 151 | #define SKIP(state_value) \ 152 | { \ 153 | skip = true; \ 154 | state = state_value; \ 155 | goto next_state; \ 156 | } 157 | 158 | #define ACCEPT_TOKEN(symbol_value) \ 159 | result = true; \ 160 | lexer->result_symbol = symbol_value; \ 161 | lexer->mark_end(lexer); 162 | 163 | #define END_STATE() return result; 164 | 165 | /* 166 | * Parse Table Macros 167 | */ 168 | 169 | #define SMALL_STATE(id) id - LARGE_STATE_COUNT 170 | 171 | #define STATE(id) id 172 | 173 | #define ACTIONS(id) id 174 | 175 | #define SHIFT(state_value) \ 176 | {{ \ 177 | .shift = { \ 178 | .type = TSParseActionTypeShift, \ 179 | .state = state_value \ 180 | } \ 181 | }} 182 | 183 | #define SHIFT_REPEAT(state_value) \ 184 | {{ \ 185 | .shift = { \ 186 | .type = TSParseActionTypeShift, \ 187 | .state = state_value, \ 188 | .repetition = true \ 189 | } \ 190 | }} 191 | 192 | #define SHIFT_EXTRA() \ 193 | {{ \ 194 | .shift = { \ 195 | .type = TSParseActionTypeShift, \ 196 | .extra = true \ 197 | } \ 198 | }} 199 | 200 | #define REDUCE(symbol_val, child_count_val, ...) \ 201 | {{ \ 202 | .reduce = { \ 203 | .type = TSParseActionTypeReduce, \ 204 | .symbol = symbol_val, \ 205 | .child_count = child_count_val, \ 206 | __VA_ARGS__ \ 207 | }, \ 208 | }} 209 | 210 | #define RECOVER() \ 211 | {{ \ 212 | .type = TSParseActionTypeRecover \ 213 | }} 214 | 215 | #define ACCEPT_INPUT() \ 216 | {{ \ 217 | .type = TSParseActionTypeAccept \ 218 | }} 219 | 220 | #ifdef __cplusplus 221 | } 222 | #endif 223 | 224 | #endif // TREE_SITTER_PARSER_H_ 225 | -------------------------------------------------------------------------------- /css-in-js-mode.el: -------------------------------------------------------------------------------- 1 | ;;; css-in-js-mode.el --- CSS-in-JS minor mode -*- lexical-binding: t; -*- 2 | 3 | ;;; Version: 20250316.0 4 | 5 | ;;; Commentary: 6 | 7 | ;;; Code: 8 | 9 | (require 'css-mode) 10 | (require 'treesit) 11 | (require 'typescript-ts-mode) 12 | 13 | (defgroup css-in-js-mode nil 14 | "CSS-in-JS minor mode." 15 | :group 'programming 16 | :prefix "css-in-js-mode-") 17 | 18 | 19 | (defconst css-in-js--treesit-library--archives 20 | "https://github.com/orzechowskid/tree-sitter-css-in-js/releases/download/latest/" 21 | "Location of archives containing tree-sitter CSS-in-JS shared libraries.") 22 | 23 | 24 | (defcustom css-in-js-mode-force-highlighting t 25 | "Enable/disable always-on CSS-in-JS syntax highlighting. 26 | Default behavior is to always highlight all regions. set to `nil' to only 27 | highlight the region containing point (if any)." 28 | :type 'boolean 29 | :group 'css-in-js-mode 30 | :package-version '(css-in-js-mode "1.0")) 31 | 32 | (defcustom css-in-js-mode-leading-indentation 33 | t 34 | "Enable/configure/disable the amount of leading indentation for CSS-in-JS. 35 | The default behavior (value of `t') is to indent each CSS-in-JS region by the 36 | value of `css-indent-offset'. Setting this to a number value will indent each 37 | CSS-in-JS region by that number of columns." 38 | :type '(choice (const :tag "None" 0) 39 | (const :tag "Use css-indent-offset" t) 40 | (integer :tag "Fixed number of columns")) 41 | :group 'css-in-js-mode 42 | :package-version '(css-in-js-mode "1.0")) 43 | 44 | (defcustom css-in-js-mode-show-color-values 45 | t 46 | "Enable/disable the rendering of CSS color values using the color they specify. 47 | The default behavior (value of `t') is to render any X11 or #RRGGBB color value 48 | using the color specified by that value." 49 | :type 'boolean 50 | :group 'css-in-js-mode 51 | :package-version '(css-in-js-mode "1.0")) 52 | 53 | 54 | (defvar css-in-js-mode--region-queries 55 | '( 56 | ;; styled-components, emotion, etc. 57 | ;; styled.foo`` 58 | ((member_expression ((identifier) @_id1) (:match "styled" @_id1)) (template_string) @ts1) 59 | ;; styled(Foo)`` 60 | ((call_expression (identifier) @_id2) (:match "styled" @_id2) (template_string) @ts2) 61 | ;; css`` 62 | ((call_expression (identifier) @_id3 (:match "css" @_id3) (template_string) @ts3)) 63 | 64 | ;; styled-jsx 65 | ;; 66 | ((jsx_element (jsx_opening_element (identifier) @_name4 (:match "style" @_name4) (jsx_attribute (property_identifier) @_attr4 (:match "jsx" @_attr4))) (jsx_expression (template_string) @ts4))) 67 | 68 | ;; Qwik - useStyles$(``) or useStylesScoped$(``) 69 | ((call_expression (identifier) @_id5 (:match "^useStyles\\(Scoped\\)?\\$" @_id5) (arguments (template_string) @ts5))) 70 | ) 71 | "Typescript-grammar treesit queries targeting various CSS-in-JS regions.") 72 | 73 | (defvar css-in-js-mode--font-lock-settings 74 | ;; TODO: open an enhancement against css-mode.el which exposes these rules via 75 | ;; a function which takes a language and returns a list, like what 76 | ;; typescript-ts-mode.el does, so that the same rules can be consumed here. 77 | ;; until then, we copypasta 78 | (treesit-font-lock-rules 79 | :feature 'comment 80 | :language 'css-in-js 81 | :override t 82 | '((comment) @font-lock-comment-face) 83 | 84 | :feature 'string 85 | :language 'css-in-js 86 | :override t 87 | '((string_value) @font-lock-string-face) 88 | 89 | :feature 'keyword 90 | :language 'css-in-js 91 | :override t 92 | '(["@media" 93 | "@import" 94 | "@charset" 95 | "@namespace" 96 | "@keyframes"] @font-lock-builtin-face 97 | ["and" 98 | "or" 99 | "not" 100 | "only" 101 | "selector"] @font-lock-keyword-face) 102 | 103 | :feature 'variable 104 | :language 'css-in-js 105 | :override t 106 | '((plain_value) @font-lock-variable-name-face) 107 | 108 | :feature 'operator 109 | :language 'css-in-js 110 | :override t 111 | `(["=" "~=" "^=" "|=" "*=" "$="] @font-lock-operator-face) 112 | 113 | :feature 'selector 114 | :language 'css-in-js 115 | :override t 116 | '((class_selector) @css-selector 117 | (child_selector) @css-selector 118 | (id_selector) @css-selector 119 | (attribute_selector) @css-selector 120 | (tag_name) @css-selector 121 | (class_name) @css-selector) 122 | 123 | :feature 'property 124 | :language 'css-in-js 125 | :override t 126 | '((property_name) @css-property) 127 | 128 | :feature 'function 129 | :language 'css-in-js 130 | :override t 131 | '((function_name) @font-lock-function-name-face) 132 | 133 | :feature 'constant 134 | :language 'css-in-js 135 | :override t 136 | '((integer_value) @font-lock-number-face 137 | (float_value) @font-lock-number-face 138 | (unit) @font-lock-constant-face 139 | ;; e.g. `width: ${foo}px;` 140 | (declaration ((js_interpolation) (plain_value) @font-lock-constant-face (:match "px\\|em\\|rem\\|vw\\|vh" @font-lock-constant-face))) 141 | (important) @font-lock-builtin-face) 142 | 143 | :feature 'query 144 | :language 'css-in-js 145 | :override t 146 | '((keyword_query) @font-lock-property-use-face 147 | (feature_name) @font-lock-property-use-face) 148 | 149 | :feature 'bracket 150 | :language 'css-in-js 151 | :override t 152 | '((["(" ")" "[" "]" "{" "}"]) @font-lock-bracket-face) 153 | 154 | :language 'css-in-js 155 | :feature 'property_values 156 | :override t 157 | '((plain_value) @css-in-js-mode--fontify-property-value 158 | (color_value) @css-in-js-mode--fontify-property-value)) 159 | "Treesit configuration for CSS-in-JS syntax highlighting.") 160 | 161 | (defvar css-in-js-mode--font-lock-feature-list 162 | '((selector comment query keyword) 163 | (property constant string) 164 | (variable function operator bracket property_values)) 165 | "Font-lock features applicable at different treesit font-lock levels.") 166 | 167 | (defvar css-in-js-mode--indent-rules 168 | `(css-in-js 169 | ;; a treesit parser root node spans the entire buffer, but CSS-in-JS 170 | ;; indentation may be different for individual regions due to indentation of 171 | ;; the JS template_string itself. anything with a parent of "stylesheet" is 172 | ;; is at the top level of its CSS-in-JS region and is treated specially 173 | ((parent-is "stylesheet") 174 | css-in-js-mode--get-stylesheet-anchor 175 | ,(if (numberp css-in-js-mode-leading-indentation) 176 | css-in-js-mode-leading-indentation 177 | css-indent-offset)) 178 | ;; regular treesit simple indent rules 179 | ((node-is "}") parent-bol 0) 180 | ((node-is ")") parent-bol 0) 181 | ((parent-is "block") parent-bol css-indent-offset) 182 | ((parent-is "declaration") parent-bol css-indent-offset) 183 | ((parent-is "feature_query") parent-bol css-indent-offset)) 184 | "List of treesit configuration objects for CSS-in-JS indentation.") 185 | 186 | 187 | (defvar-local css-in-js-mode--major-mode-lang 188 | nil 189 | "Internal variable. The treesit language belonging to the parent major mode.") 190 | 191 | (defvar-local css-in-js--previous-comment-dwim-remapping 192 | nil 193 | "Internal variable. Store previous `comment-dwim' remapping before we remap it.") 194 | 195 | (defvar-local css-in-js--treesit-parser 196 | nil 197 | "Internal variable. Store the `css-in-js' parser.") 198 | 199 | (defun css-in-js-mode--get-stylesheet-anchor (node &rest _ignored) 200 | "Return an indentation anchor point based on the containing region of NODE." 201 | (let ((region-for-node (css-in-js-mode--get-region-for-node node))) 202 | (if region-for-node 203 | (+ 1 204 | (save-excursion 205 | (goto-char (car region-for-node)) 206 | (back-to-indentation) 207 | (current-column))) 208 | 0))) 209 | 210 | (defun css-in-js-mode--fontify-property-value (node &rest _ignored) 211 | "Conditionally apply font-locking to rule values inside of NODE." 212 | (let ((buffer-start (treesit-node-start node)) 213 | (buffer-end (treesit-node-end node)) 214 | (text (treesit-node-text node))) 215 | (cond 216 | ((and css-in-js-mode-show-color-values 217 | (or (member text x-colors) 218 | (string= (treesit-node-type node) "color_value"))) 219 | (add-text-properties 220 | buffer-start buffer-end 221 | (list 'face (append 222 | (list :background text) 223 | (condition-case nil 224 | (list :foreground (readable-foreground-color text)) 225 | (error nil)))))) 226 | ((or (string= text "initial") 227 | (string= text "inherit") 228 | (string= text "auto") 229 | (string= text "unset")) 230 | (add-text-properties 231 | buffer-start buffer-end 232 | '(face font-lock-builtin-face)))))) 233 | 234 | (defun css-in-js-mode--treesit-set-ranges (&rest _ignored) 235 | "Update the range info for tree-sitter parsers in this buffer." 236 | (when css-in-js-mode 237 | (treesit-parser-set-included-ranges 238 | css-in-js--treesit-parser 239 | (or 240 | (seq-map 241 | (lambda (el) 242 | (cons 243 | ;; slice off the template-string delimiters 244 | (1+ (treesit-node-start (cdr el))) 245 | (save-excursion (goto-char (1- (treesit-node-end (cdr el)))) 246 | (skip-chars-backward " \t\n\r") 247 | (point)))) 248 | (seq-filter 249 | (lambda (el) 250 | (let* ((node (cdr el)) 251 | (start (treesit-node-start node)) 252 | (end (treesit-node-end node))) 253 | (and 254 | (equal (treesit-node-type node) 255 | "template_string") 256 | (> (- end start) 2)))) ; filter out empty template_string nodes 257 | (treesit-query-capture 258 | (treesit-buffer-root-node css-in-js-mode--major-mode-lang) 259 | css-in-js-mode--region-queries 260 | (point-min) (point-max)))) 261 | ;; providing nil to `treesit-parser-set-included-ranges' tells it to span 262 | ;; the entire buffer, so instead we provide a dummy range of length zero 263 | (list (cons (point-max) (point-max))))))) 264 | 265 | (defun css-in-js-mode--get-language-at-pos (pos) 266 | "Return the treesit language at buffer position POS. 267 | 268 | The language will be either css-in-js or the major mode's host language. This 269 | function is suitable for use as `treesit-language-at-point-function'." 270 | (if (and css-in-js-mode (seq-find 271 | (lambda (el) 272 | (and (>= pos (car el)) 273 | (<= pos (cdr el)))) 274 | (treesit-parser-included-ranges css-in-js--treesit-parser))) 275 | 'css-in-js 276 | css-in-js-mode--major-mode-lang)) 277 | 278 | (defun css-in-js-mode--get-region-for-node (node) 279 | "Return the css-in-js region containing node NODE, or nil." 280 | (when node 281 | (let ((node-start (treesit-node-start node))) 282 | (seq-find 283 | (lambda (el) 284 | ;; test that node-start is inside the current range. (but don't test 285 | ;; that node-end is inside the range too! that can result in false 286 | ;; negatives when there are syntax errors inside of CSS-in-JS nodes) 287 | (and (>= node-start (car el)) 288 | (<= node-start (cdr el)))) 289 | (treesit-parser-included-ranges css-in-js--treesit-parser) 290 | nil)))) 291 | 292 | (defun css-in-js-mode--current-region () 293 | "Get the boundaries of the current CSS-in-JS region. 294 | Returns a cons cell (start . end) of buffer locations." 295 | (seq-find 296 | (lambda (el) 297 | ;; ranges by definition are sorted and non-overlapping 298 | (<= (point) (cdr el))) 299 | (treesit-parser-included-ranges css-in-js--treesit-parser))) 300 | 301 | (defun css-in-js-mode--complete-property () 302 | "`css--complete-property' modified for CSS-in-JS." 303 | ;; the original expects properties to be preceded with a '{' or ';' which will 304 | ;; not be the case for top-level CSS rules in CSS-in-JS regions (we need to 305 | ;; search for backticks too) 306 | (save-excursion 307 | (let ((pos (point))) 308 | (skip-chars-backward "-[:alnum:]") 309 | (let ((start (point))) 310 | (skip-chars-backward " \t\r\n") 311 | (when (memq (char-before) '(?\{ ?\; ?\`)) 312 | (list start pos css-property-ids)))))) 313 | 314 | (defun css-in-js-mode--complete-property-value () 315 | "`css--complete-property-value' modified for CSS-in-JS." 316 | ;; the original uses `syntax-ppss' to restrict the lookback area, which seems 317 | ;; to apply to tsx sexps instead of css-in-js ones 318 | (save-excursion 319 | (save-match-data 320 | (let ((property 321 | (and (looking-back 322 | "\\([[:alnum:]-]+\\):.*" 323 | (min (point) (car (css-in-js-mode--current-region))) 324 | t) 325 | (member (match-string-no-properties 1) 326 | css-property-ids)))) 327 | (when property 328 | (let ((end (point))) 329 | (save-excursion 330 | (skip-chars-backward "[:graph:]") 331 | (list (point) end 332 | (append '("inherit" "initial" "unset") 333 | (css--property-values (car property))) 334 | :company-kind (lambda (_) 'value))))))))) 335 | 336 | (defun css-in-js-mode--capf () 337 | "`completion-at-point' function for `css-in-js-mode'." 338 | (when (eq (treesit-language-at (point)) 'css-in-js) 339 | (or (css-in-js-mode--complete-property) 340 | (css-in-js-mode--complete-property-value) 341 | (css-completion-at-point)))) 342 | 343 | (defun css-in-js-comment-dwim (arg) 344 | "Add support for commenting/uncommenting inside css in js. 345 | See `comment-dwim' documentation for ARG usage." 346 | (interactive "P") 347 | (if (eq (css-in-js-mode--get-language-at-pos (point)) 'css-in-js) 348 | (let ((comment-start "/* ") 349 | (comment-end " */")) 350 | (comment-dwim arg)) 351 | (if css-in-js--previous-comment-dwim-remapping 352 | (funcall css-in-js--previous-comment-dwim-remapping arg) 353 | (comment-dwim arg)))) 354 | 355 | (define-minor-mode css-in-js-mode 356 | "a minor mode for some flavors of CSS-in-JS." 357 | :lighter " CSS+JS" 358 | :group 'css-in-js-mode 359 | :version "29.0" 360 | (when (treesit-ready-p 'css-in-js) 361 | (pcase css-in-js-mode 362 | ('t 363 | ;; store a reference to the language configured by the major mode 364 | ;; FIXME: this is fragile - it seems like an implementation detail that new 365 | ;; treesit parsers are added to the head of the list returned by 366 | ;; `treesit-parser-list' 367 | (setq-local 368 | css-in-js-mode--major-mode-lang 369 | (treesit-parser-language (car (treesit-parser-list)))) 370 | ;; mode is being enabled 371 | (message "enabling...") 372 | ;; create parser 373 | (setq-local css-in-js--treesit-parser (treesit-parser-create 'css-in-js)) 374 | ;; configure range definitions 375 | (setq-local 376 | treesit-range-settings 377 | (append 378 | treesit-range-settings 379 | (treesit-range-rules 380 | #'css-in-js-mode--treesit-set-ranges))) 381 | ;; configure language-at-point sniffer 382 | (setq-local 383 | treesit-language-at-point-function 384 | #'css-in-js-mode--get-language-at-pos) 385 | ;; configure font-locking 386 | (setq-local 387 | treesit-font-lock-settings 388 | (append 389 | treesit-font-lock-settings 390 | css-in-js-mode--font-lock-settings)) 391 | (setq-local 392 | treesit-font-lock-feature-list 393 | (seq-mapn 394 | #'append 395 | treesit-font-lock-feature-list css-in-js-mode--font-lock-feature-list)) 396 | ;; configure indentation 397 | (add-to-list 'treesit-simple-indent-rules css-in-js-mode--indent-rules t) 398 | ;; apply treesit-related changes 399 | (treesit-major-mode-setup) 400 | ;; force refontification (needed starting 29.2, cf bug #66223) 401 | (treesit-font-lock-fontify-region (point-min) (point-max)) 402 | ;; configure capf 403 | (add-hook 404 | 'completion-at-point-functions 405 | #'css-in-js-mode--capf 406 | nil t) 407 | ;; comments support 408 | (setq-local css-in-js--previous-comment-dwim-remapping (command-remapping 'comment-dwim)) 409 | (define-key (current-local-map) [remap comment-dwim] 'css-in-js-comment-dwim) 410 | ;; (add-hook 411 | ;; 'post-command-hook 412 | ;; #'css-in-js-mode--fontify-post-command 413 | ;; nil t) 414 | ) 415 | ('nil 416 | ;; mode is being disabled 417 | (message "disabling...") 418 | ;; remove comments support 419 | (define-key (current-local-map) [remap comment-dwim] 420 | css-in-js--previous-comment-dwim-remapping) 421 | ;; remove parser 422 | ;; TODO: graceful removal of range settings (right now our range-setting 423 | ;; function just checks that this mode is not disabled) 424 | (treesit-parser-delete css-in-js--treesit-parser) 425 | )))) 426 | 427 | ;; (setq-local 428 | ;; css-in-js-mode--major-mode-lang 429 | ;; (treesit-parser-language (car (treesit-parser-list)))) 430 | ;; (treesit-parser-create 'css-in-js) 431 | ;; (css-in-js-mode--treesit-set-ranges (point-min) (point-max)) 432 | ;; (message "ranges: %s" (treesit-parser-included-ranges (treesit-parser-create 'css-in-js))))) 433 | 434 | ;; ;;;###xxxautoload 435 | ;; (define-minor-mode css-in-js-mode 436 | ;; "A minor mode adding CSS-in-JS support to your treesit-based major mode." 437 | ;; :lighter " CSS+JS" 438 | ;; :group 'css-in-js-mode 439 | ;; :version "29.0" 440 | ;; (pcase css-in-js-mode 441 | ;; ;; enabling 442 | ;; ('t 443 | ;; ;; store a reference to the language configured by the major mode 444 | ;; (setq-local 445 | ;; css-in-js-mode--major-mode-lang 446 | ;; (treesit-parser-language (car (treesit-parser-list)))) 447 | ;; (when (treesit-ready-p 'css-in-js) 448 | ;; ;; configure range definitions 449 | ;; (setq-local 450 | ;; treesit-language-at-point-function 451 | ;; #'css-in-js-mode--get-language-at-pos) 452 | ;; (setq-local 453 | ;; treesit-range-settings 454 | ;; (append 455 | ;; treesit-range-settings 456 | ;; (treesit-range-rules 457 | ;; 'css-in-js-mode--treesit-set-ranges))) 458 | ;; ;; configure font-lock 459 | ;; (if css-in-js-mode-force-highlighting 460 | ;; (setq-local 461 | ;; treesit-font-lock-settings 462 | ;; (append 463 | ;; treesit-font-lock-settings 464 | ;; css-in-js-mode--font-lock-settings)) 465 | ;; (progn 466 | ;; ;; this does something weird with strings and ppss that I don't like 467 | ;; (setq-local jit-lock-antiblink-grace 0) 468 | ;; (add-hook 469 | ;; 'post-command-hook 470 | ;; #'css-in-js-mode--fontify-post-command 471 | ;; nil t))) 472 | ;; (setq-local 473 | ;; treesit-font-lock-feature-list 474 | ;; (seq-mapn 475 | ;; #'append 476 | ;; treesit-font-lock-feature-list css-in-js-mode--font-lock-feature-list)) 477 | ;; ;; configure indentation 478 | ;; (setq-local 479 | ;; treesit-indent-function 480 | ;; #'css-in-js-mode--simple-indent) 481 | ;; ;; configure capf 482 | ;; (add-hook 483 | ;; 'completion-at-point-functions 484 | ;; #'css-in-js-mode--capf 485 | ;; nil t) 486 | ;; ;; configure treesit 487 | ;; (treesit-major-mode-setup)) 488 | ;; t) 489 | ;; ;; disabling 490 | ;; ('nil 491 | ;; ;; remove parser 492 | ;; ;; TODO: graceful removal of range settings (right now our range-setting 493 | ;; ;; function just checks that this mode is not disabled) 494 | ;; (treesit-parser-delete (treesit-parser-create 'css-in-js)) 495 | ;; ;; unconfigure font-lock 496 | ;; (setq-local 497 | ;; treesit-font-lock-feature-list 498 | ;; (seq-mapn 499 | ;; #'seq-difference 500 | ;; treesit-font-lock-feature-list css-in-js-mode--font-lock-feature-list)) 501 | ;; ;; unconfigure indentation 502 | ;; (setq-local 503 | ;; treesit-indent-function 504 | ;; #'treesit-simple-indent) 505 | ;; ;; unconfigure capf 506 | ;; (remove-hook 507 | ;; 'completion-at-point-functions 508 | ;; #'css-in-js-mode--capf 509 | ;; t) 510 | ;; ;; reconfigure treesit 511 | ;; (treesit-major-mode-setup) 512 | ;; nil))) 513 | 514 | 515 | (defconst css-in-js-mode--treesit-archive-filename 516 | (cond 517 | ((eq system-type 'windows-nt) 518 | "windows.tar.gz") 519 | ((eq system-type 'darwin) 520 | "macos.tar.gz") 521 | (t "linux.tar.gz")) 522 | "The name of a shared-library archive appropriate for the current OS and 523 | hardware.") 524 | 525 | 526 | (defun css-in-js-mode--treesit-shared-library-path () 527 | "Returns the absolute path to a filesystem directory suitable for storing 528 | tree-sitter shared libraries." 529 | (let ((path (expand-file-name (file-name-concat user-emacs-directory "tree-sitter")))) 530 | (make-directory path t) 531 | path)) 532 | 533 | ;;;###autoload 534 | (defun css-in-js-mode-fetch-shared-library (&optional force) 535 | "Fetches a remote archive containing a tree-sitter shared library suitable for 536 | the current OS+CPU, uncompresses it, and stores it in a location accessible by 537 | treesit. 538 | Skips re-downloading if the archive is already present on disk, unless FORCE is 539 | set to `t'." 540 | (let* ((archive-name css-in-js-mode--treesit-archive-filename) 541 | (lib-dir (css-in-js-mode--treesit-shared-library-path)) 542 | (archive-fs-path (file-name-concat lib-dir archive-name))) 543 | (when (or (not (file-exists-p archive-fs-path)) 544 | force) 545 | (message "fetching CSS-in-JS shared library...") 546 | (url-copy-file 547 | (concat css-in-js--treesit-library--archives archive-name) 548 | archive-fs-path 549 | t) 550 | (= 0 (call-process 551 | "tar" 552 | nil nil nil 553 | "-C" lib-dir "-zxf" archive-fs-path))))) 554 | 555 | 556 | (provide 'css-in-js-mode) 557 | -------------------------------------------------------------------------------- /src/node-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "adjacent_sibling_selector", 4 | "named": true, 5 | "fields": {}, 6 | "children": { 7 | "multiple": true, 8 | "required": true, 9 | "types": [ 10 | { 11 | "type": "adjacent_sibling_selector", 12 | "named": true 13 | }, 14 | { 15 | "type": "attribute_selector", 16 | "named": true 17 | }, 18 | { 19 | "type": "child_selector", 20 | "named": true 21 | }, 22 | { 23 | "type": "class_selector", 24 | "named": true 25 | }, 26 | { 27 | "type": "descendant_selector", 28 | "named": true 29 | }, 30 | { 31 | "type": "id_selector", 32 | "named": true 33 | }, 34 | { 35 | "type": "namespace_selector", 36 | "named": true 37 | }, 38 | { 39 | "type": "nesting_selector", 40 | "named": true 41 | }, 42 | { 43 | "type": "pseudo_class_selector", 44 | "named": true 45 | }, 46 | { 47 | "type": "pseudo_element_selector", 48 | "named": true 49 | }, 50 | { 51 | "type": "sibling_selector", 52 | "named": true 53 | }, 54 | { 55 | "type": "string_value", 56 | "named": true 57 | }, 58 | { 59 | "type": "tag_name", 60 | "named": true 61 | }, 62 | { 63 | "type": "universal_selector", 64 | "named": true 65 | } 66 | ] 67 | } 68 | }, 69 | { 70 | "type": "arguments", 71 | "named": true, 72 | "fields": {}, 73 | "children": { 74 | "multiple": true, 75 | "required": false, 76 | "types": [ 77 | { 78 | "type": "adjacent_sibling_selector", 79 | "named": true 80 | }, 81 | { 82 | "type": "attribute_selector", 83 | "named": true 84 | }, 85 | { 86 | "type": "binary_expression", 87 | "named": true 88 | }, 89 | { 90 | "type": "call_expression", 91 | "named": true 92 | }, 93 | { 94 | "type": "child_selector", 95 | "named": true 96 | }, 97 | { 98 | "type": "class_selector", 99 | "named": true 100 | }, 101 | { 102 | "type": "color_value", 103 | "named": true 104 | }, 105 | { 106 | "type": "descendant_selector", 107 | "named": true 108 | }, 109 | { 110 | "type": "float_value", 111 | "named": true 112 | }, 113 | { 114 | "type": "grid_value", 115 | "named": true 116 | }, 117 | { 118 | "type": "id_selector", 119 | "named": true 120 | }, 121 | { 122 | "type": "important", 123 | "named": true 124 | }, 125 | { 126 | "type": "integer_value", 127 | "named": true 128 | }, 129 | { 130 | "type": "namespace_selector", 131 | "named": true 132 | }, 133 | { 134 | "type": "nesting_selector", 135 | "named": true 136 | }, 137 | { 138 | "type": "parenthesized_value", 139 | "named": true 140 | }, 141 | { 142 | "type": "plain_value", 143 | "named": true 144 | }, 145 | { 146 | "type": "pseudo_class_selector", 147 | "named": true 148 | }, 149 | { 150 | "type": "pseudo_element_selector", 151 | "named": true 152 | }, 153 | { 154 | "type": "sibling_selector", 155 | "named": true 156 | }, 157 | { 158 | "type": "string_value", 159 | "named": true 160 | }, 161 | { 162 | "type": "tag_name", 163 | "named": true 164 | }, 165 | { 166 | "type": "universal_selector", 167 | "named": true 168 | } 169 | ] 170 | } 171 | }, 172 | { 173 | "type": "at_rule", 174 | "named": true, 175 | "fields": {}, 176 | "children": { 177 | "multiple": true, 178 | "required": true, 179 | "types": [ 180 | { 181 | "type": "at_keyword", 182 | "named": true 183 | }, 184 | { 185 | "type": "binary_query", 186 | "named": true 187 | }, 188 | { 189 | "type": "block", 190 | "named": true 191 | }, 192 | { 193 | "type": "feature_query", 194 | "named": true 195 | }, 196 | { 197 | "type": "keyword_query", 198 | "named": true 199 | }, 200 | { 201 | "type": "parenthesized_query", 202 | "named": true 203 | }, 204 | { 205 | "type": "selector_query", 206 | "named": true 207 | }, 208 | { 209 | "type": "unary_query", 210 | "named": true 211 | } 212 | ] 213 | } 214 | }, 215 | { 216 | "type": "attribute_name", 217 | "named": true, 218 | "fields": {}, 219 | "children": { 220 | "multiple": true, 221 | "required": false, 222 | "types": [ 223 | { 224 | "type": "adjacent_sibling_selector", 225 | "named": true 226 | }, 227 | { 228 | "type": "attribute_selector", 229 | "named": true 230 | }, 231 | { 232 | "type": "child_selector", 233 | "named": true 234 | }, 235 | { 236 | "type": "class_selector", 237 | "named": true 238 | }, 239 | { 240 | "type": "descendant_selector", 241 | "named": true 242 | }, 243 | { 244 | "type": "id_selector", 245 | "named": true 246 | }, 247 | { 248 | "type": "namespace_selector", 249 | "named": true 250 | }, 251 | { 252 | "type": "nesting_selector", 253 | "named": true 254 | }, 255 | { 256 | "type": "pseudo_class_selector", 257 | "named": true 258 | }, 259 | { 260 | "type": "pseudo_element_selector", 261 | "named": true 262 | }, 263 | { 264 | "type": "sibling_selector", 265 | "named": true 266 | }, 267 | { 268 | "type": "string_value", 269 | "named": true 270 | }, 271 | { 272 | "type": "tag_name", 273 | "named": true 274 | }, 275 | { 276 | "type": "universal_selector", 277 | "named": true 278 | } 279 | ] 280 | } 281 | }, 282 | { 283 | "type": "attribute_selector", 284 | "named": true, 285 | "fields": {}, 286 | "children": { 287 | "multiple": true, 288 | "required": true, 289 | "types": [ 290 | { 291 | "type": "adjacent_sibling_selector", 292 | "named": true 293 | }, 294 | { 295 | "type": "attribute_name", 296 | "named": true 297 | }, 298 | { 299 | "type": "attribute_selector", 300 | "named": true 301 | }, 302 | { 303 | "type": "binary_expression", 304 | "named": true 305 | }, 306 | { 307 | "type": "call_expression", 308 | "named": true 309 | }, 310 | { 311 | "type": "child_selector", 312 | "named": true 313 | }, 314 | { 315 | "type": "class_selector", 316 | "named": true 317 | }, 318 | { 319 | "type": "color_value", 320 | "named": true 321 | }, 322 | { 323 | "type": "descendant_selector", 324 | "named": true 325 | }, 326 | { 327 | "type": "float_value", 328 | "named": true 329 | }, 330 | { 331 | "type": "grid_value", 332 | "named": true 333 | }, 334 | { 335 | "type": "id_selector", 336 | "named": true 337 | }, 338 | { 339 | "type": "important", 340 | "named": true 341 | }, 342 | { 343 | "type": "integer_value", 344 | "named": true 345 | }, 346 | { 347 | "type": "namespace_selector", 348 | "named": true 349 | }, 350 | { 351 | "type": "nesting_selector", 352 | "named": true 353 | }, 354 | { 355 | "type": "parenthesized_value", 356 | "named": true 357 | }, 358 | { 359 | "type": "plain_value", 360 | "named": true 361 | }, 362 | { 363 | "type": "pseudo_class_selector", 364 | "named": true 365 | }, 366 | { 367 | "type": "pseudo_element_selector", 368 | "named": true 369 | }, 370 | { 371 | "type": "sibling_selector", 372 | "named": true 373 | }, 374 | { 375 | "type": "string_value", 376 | "named": true 377 | }, 378 | { 379 | "type": "tag_name", 380 | "named": true 381 | }, 382 | { 383 | "type": "universal_selector", 384 | "named": true 385 | } 386 | ] 387 | } 388 | }, 389 | { 390 | "type": "binary_expression", 391 | "named": true, 392 | "fields": {}, 393 | "children": { 394 | "multiple": true, 395 | "required": true, 396 | "types": [ 397 | { 398 | "type": "binary_expression", 399 | "named": true 400 | }, 401 | { 402 | "type": "call_expression", 403 | "named": true 404 | }, 405 | { 406 | "type": "color_value", 407 | "named": true 408 | }, 409 | { 410 | "type": "float_value", 411 | "named": true 412 | }, 413 | { 414 | "type": "grid_value", 415 | "named": true 416 | }, 417 | { 418 | "type": "important", 419 | "named": true 420 | }, 421 | { 422 | "type": "integer_value", 423 | "named": true 424 | }, 425 | { 426 | "type": "parenthesized_value", 427 | "named": true 428 | }, 429 | { 430 | "type": "plain_value", 431 | "named": true 432 | }, 433 | { 434 | "type": "string_value", 435 | "named": true 436 | } 437 | ] 438 | } 439 | }, 440 | { 441 | "type": "binary_query", 442 | "named": true, 443 | "fields": {}, 444 | "children": { 445 | "multiple": true, 446 | "required": true, 447 | "types": [ 448 | { 449 | "type": "binary_query", 450 | "named": true 451 | }, 452 | { 453 | "type": "feature_query", 454 | "named": true 455 | }, 456 | { 457 | "type": "keyword_query", 458 | "named": true 459 | }, 460 | { 461 | "type": "parenthesized_query", 462 | "named": true 463 | }, 464 | { 465 | "type": "selector_query", 466 | "named": true 467 | }, 468 | { 469 | "type": "unary_query", 470 | "named": true 471 | } 472 | ] 473 | } 474 | }, 475 | { 476 | "type": "block", 477 | "named": true, 478 | "fields": {}, 479 | "children": { 480 | "multiple": true, 481 | "required": false, 482 | "types": [ 483 | { 484 | "type": "at_rule", 485 | "named": true 486 | }, 487 | { 488 | "type": "charset_statement", 489 | "named": true 490 | }, 491 | { 492 | "type": "declaration", 493 | "named": true 494 | }, 495 | { 496 | "type": "import_statement", 497 | "named": true 498 | }, 499 | { 500 | "type": "js_interpolation", 501 | "named": true 502 | }, 503 | { 504 | "type": "keyframes_statement", 505 | "named": true 506 | }, 507 | { 508 | "type": "media_statement", 509 | "named": true 510 | }, 511 | { 512 | "type": "namespace_statement", 513 | "named": true 514 | }, 515 | { 516 | "type": "postcss_statement", 517 | "named": true 518 | }, 519 | { 520 | "type": "rule_set", 521 | "named": true 522 | }, 523 | { 524 | "type": "supports_statement", 525 | "named": true 526 | } 527 | ] 528 | } 529 | }, 530 | { 531 | "type": "call_expression", 532 | "named": true, 533 | "fields": {}, 534 | "children": { 535 | "multiple": true, 536 | "required": true, 537 | "types": [ 538 | { 539 | "type": "arguments", 540 | "named": true 541 | }, 542 | { 543 | "type": "function_name", 544 | "named": true 545 | } 546 | ] 547 | } 548 | }, 549 | { 550 | "type": "charset_statement", 551 | "named": true, 552 | "fields": {}, 553 | "children": { 554 | "multiple": false, 555 | "required": true, 556 | "types": [ 557 | { 558 | "type": "binary_expression", 559 | "named": true 560 | }, 561 | { 562 | "type": "call_expression", 563 | "named": true 564 | }, 565 | { 566 | "type": "color_value", 567 | "named": true 568 | }, 569 | { 570 | "type": "float_value", 571 | "named": true 572 | }, 573 | { 574 | "type": "grid_value", 575 | "named": true 576 | }, 577 | { 578 | "type": "important", 579 | "named": true 580 | }, 581 | { 582 | "type": "integer_value", 583 | "named": true 584 | }, 585 | { 586 | "type": "parenthesized_value", 587 | "named": true 588 | }, 589 | { 590 | "type": "plain_value", 591 | "named": true 592 | }, 593 | { 594 | "type": "string_value", 595 | "named": true 596 | } 597 | ] 598 | } 599 | }, 600 | { 601 | "type": "child_selector", 602 | "named": true, 603 | "fields": {}, 604 | "children": { 605 | "multiple": true, 606 | "required": true, 607 | "types": [ 608 | { 609 | "type": "adjacent_sibling_selector", 610 | "named": true 611 | }, 612 | { 613 | "type": "attribute_selector", 614 | "named": true 615 | }, 616 | { 617 | "type": "child_selector", 618 | "named": true 619 | }, 620 | { 621 | "type": "class_selector", 622 | "named": true 623 | }, 624 | { 625 | "type": "descendant_selector", 626 | "named": true 627 | }, 628 | { 629 | "type": "id_selector", 630 | "named": true 631 | }, 632 | { 633 | "type": "namespace_selector", 634 | "named": true 635 | }, 636 | { 637 | "type": "nesting_selector", 638 | "named": true 639 | }, 640 | { 641 | "type": "pseudo_class_selector", 642 | "named": true 643 | }, 644 | { 645 | "type": "pseudo_element_selector", 646 | "named": true 647 | }, 648 | { 649 | "type": "sibling_selector", 650 | "named": true 651 | }, 652 | { 653 | "type": "string_value", 654 | "named": true 655 | }, 656 | { 657 | "type": "tag_name", 658 | "named": true 659 | }, 660 | { 661 | "type": "universal_selector", 662 | "named": true 663 | } 664 | ] 665 | } 666 | }, 667 | { 668 | "type": "class_selector", 669 | "named": true, 670 | "fields": {}, 671 | "children": { 672 | "multiple": true, 673 | "required": true, 674 | "types": [ 675 | { 676 | "type": "adjacent_sibling_selector", 677 | "named": true 678 | }, 679 | { 680 | "type": "attribute_selector", 681 | "named": true 682 | }, 683 | { 684 | "type": "child_selector", 685 | "named": true 686 | }, 687 | { 688 | "type": "class_name", 689 | "named": true 690 | }, 691 | { 692 | "type": "class_selector", 693 | "named": true 694 | }, 695 | { 696 | "type": "descendant_selector", 697 | "named": true 698 | }, 699 | { 700 | "type": "id_selector", 701 | "named": true 702 | }, 703 | { 704 | "type": "namespace_selector", 705 | "named": true 706 | }, 707 | { 708 | "type": "nesting_selector", 709 | "named": true 710 | }, 711 | { 712 | "type": "pseudo_class_selector", 713 | "named": true 714 | }, 715 | { 716 | "type": "pseudo_element_selector", 717 | "named": true 718 | }, 719 | { 720 | "type": "sibling_selector", 721 | "named": true 722 | }, 723 | { 724 | "type": "string_value", 725 | "named": true 726 | }, 727 | { 728 | "type": "tag_name", 729 | "named": true 730 | }, 731 | { 732 | "type": "universal_selector", 733 | "named": true 734 | } 735 | ] 736 | } 737 | }, 738 | { 739 | "type": "color_value", 740 | "named": true, 741 | "fields": {} 742 | }, 743 | { 744 | "type": "declaration", 745 | "named": true, 746 | "fields": {}, 747 | "children": { 748 | "multiple": true, 749 | "required": true, 750 | "types": [ 751 | { 752 | "type": "binary_expression", 753 | "named": true 754 | }, 755 | { 756 | "type": "call_expression", 757 | "named": true 758 | }, 759 | { 760 | "type": "color_value", 761 | "named": true 762 | }, 763 | { 764 | "type": "float_value", 765 | "named": true 766 | }, 767 | { 768 | "type": "grid_value", 769 | "named": true 770 | }, 771 | { 772 | "type": "important", 773 | "named": true 774 | }, 775 | { 776 | "type": "integer_value", 777 | "named": true 778 | }, 779 | { 780 | "type": "js_interpolation", 781 | "named": true 782 | }, 783 | { 784 | "type": "parenthesized_value", 785 | "named": true 786 | }, 787 | { 788 | "type": "plain_value", 789 | "named": true 790 | }, 791 | { 792 | "type": "property_name", 793 | "named": true 794 | }, 795 | { 796 | "type": "string_value", 797 | "named": true 798 | } 799 | ] 800 | } 801 | }, 802 | { 803 | "type": "descendant_selector", 804 | "named": true, 805 | "fields": {}, 806 | "children": { 807 | "multiple": true, 808 | "required": true, 809 | "types": [ 810 | { 811 | "type": "adjacent_sibling_selector", 812 | "named": true 813 | }, 814 | { 815 | "type": "attribute_selector", 816 | "named": true 817 | }, 818 | { 819 | "type": "child_selector", 820 | "named": true 821 | }, 822 | { 823 | "type": "class_selector", 824 | "named": true 825 | }, 826 | { 827 | "type": "descendant_selector", 828 | "named": true 829 | }, 830 | { 831 | "type": "id_selector", 832 | "named": true 833 | }, 834 | { 835 | "type": "namespace_selector", 836 | "named": true 837 | }, 838 | { 839 | "type": "nesting_selector", 840 | "named": true 841 | }, 842 | { 843 | "type": "pseudo_class_selector", 844 | "named": true 845 | }, 846 | { 847 | "type": "pseudo_element_selector", 848 | "named": true 849 | }, 850 | { 851 | "type": "sibling_selector", 852 | "named": true 853 | }, 854 | { 855 | "type": "string_value", 856 | "named": true 857 | }, 858 | { 859 | "type": "tag_name", 860 | "named": true 861 | }, 862 | { 863 | "type": "universal_selector", 864 | "named": true 865 | } 866 | ] 867 | } 868 | }, 869 | { 870 | "type": "feature_query", 871 | "named": true, 872 | "fields": {}, 873 | "children": { 874 | "multiple": true, 875 | "required": true, 876 | "types": [ 877 | { 878 | "type": "binary_expression", 879 | "named": true 880 | }, 881 | { 882 | "type": "call_expression", 883 | "named": true 884 | }, 885 | { 886 | "type": "color_value", 887 | "named": true 888 | }, 889 | { 890 | "type": "feature_name", 891 | "named": true 892 | }, 893 | { 894 | "type": "float_value", 895 | "named": true 896 | }, 897 | { 898 | "type": "grid_value", 899 | "named": true 900 | }, 901 | { 902 | "type": "important", 903 | "named": true 904 | }, 905 | { 906 | "type": "integer_value", 907 | "named": true 908 | }, 909 | { 910 | "type": "parenthesized_value", 911 | "named": true 912 | }, 913 | { 914 | "type": "plain_value", 915 | "named": true 916 | }, 917 | { 918 | "type": "string_value", 919 | "named": true 920 | } 921 | ] 922 | } 923 | }, 924 | { 925 | "type": "float_value", 926 | "named": true, 927 | "fields": {}, 928 | "children": { 929 | "multiple": false, 930 | "required": false, 931 | "types": [ 932 | { 933 | "type": "unit", 934 | "named": true 935 | } 936 | ] 937 | } 938 | }, 939 | { 940 | "type": "grid_value", 941 | "named": true, 942 | "fields": {}, 943 | "children": { 944 | "multiple": true, 945 | "required": true, 946 | "types": [ 947 | { 948 | "type": "binary_expression", 949 | "named": true 950 | }, 951 | { 952 | "type": "call_expression", 953 | "named": true 954 | }, 955 | { 956 | "type": "color_value", 957 | "named": true 958 | }, 959 | { 960 | "type": "float_value", 961 | "named": true 962 | }, 963 | { 964 | "type": "grid_value", 965 | "named": true 966 | }, 967 | { 968 | "type": "important", 969 | "named": true 970 | }, 971 | { 972 | "type": "integer_value", 973 | "named": true 974 | }, 975 | { 976 | "type": "parenthesized_value", 977 | "named": true 978 | }, 979 | { 980 | "type": "plain_value", 981 | "named": true 982 | }, 983 | { 984 | "type": "string_value", 985 | "named": true 986 | } 987 | ] 988 | } 989 | }, 990 | { 991 | "type": "id_selector", 992 | "named": true, 993 | "fields": {}, 994 | "children": { 995 | "multiple": true, 996 | "required": true, 997 | "types": [ 998 | { 999 | "type": "adjacent_sibling_selector", 1000 | "named": true 1001 | }, 1002 | { 1003 | "type": "attribute_selector", 1004 | "named": true 1005 | }, 1006 | { 1007 | "type": "child_selector", 1008 | "named": true 1009 | }, 1010 | { 1011 | "type": "class_selector", 1012 | "named": true 1013 | }, 1014 | { 1015 | "type": "descendant_selector", 1016 | "named": true 1017 | }, 1018 | { 1019 | "type": "id_name", 1020 | "named": true 1021 | }, 1022 | { 1023 | "type": "id_selector", 1024 | "named": true 1025 | }, 1026 | { 1027 | "type": "namespace_selector", 1028 | "named": true 1029 | }, 1030 | { 1031 | "type": "nesting_selector", 1032 | "named": true 1033 | }, 1034 | { 1035 | "type": "pseudo_class_selector", 1036 | "named": true 1037 | }, 1038 | { 1039 | "type": "pseudo_element_selector", 1040 | "named": true 1041 | }, 1042 | { 1043 | "type": "sibling_selector", 1044 | "named": true 1045 | }, 1046 | { 1047 | "type": "string_value", 1048 | "named": true 1049 | }, 1050 | { 1051 | "type": "tag_name", 1052 | "named": true 1053 | }, 1054 | { 1055 | "type": "universal_selector", 1056 | "named": true 1057 | } 1058 | ] 1059 | } 1060 | }, 1061 | { 1062 | "type": "import_statement", 1063 | "named": true, 1064 | "fields": {}, 1065 | "children": { 1066 | "multiple": true, 1067 | "required": true, 1068 | "types": [ 1069 | { 1070 | "type": "binary_expression", 1071 | "named": true 1072 | }, 1073 | { 1074 | "type": "binary_query", 1075 | "named": true 1076 | }, 1077 | { 1078 | "type": "call_expression", 1079 | "named": true 1080 | }, 1081 | { 1082 | "type": "color_value", 1083 | "named": true 1084 | }, 1085 | { 1086 | "type": "feature_query", 1087 | "named": true 1088 | }, 1089 | { 1090 | "type": "float_value", 1091 | "named": true 1092 | }, 1093 | { 1094 | "type": "grid_value", 1095 | "named": true 1096 | }, 1097 | { 1098 | "type": "important", 1099 | "named": true 1100 | }, 1101 | { 1102 | "type": "integer_value", 1103 | "named": true 1104 | }, 1105 | { 1106 | "type": "keyword_query", 1107 | "named": true 1108 | }, 1109 | { 1110 | "type": "parenthesized_query", 1111 | "named": true 1112 | }, 1113 | { 1114 | "type": "parenthesized_value", 1115 | "named": true 1116 | }, 1117 | { 1118 | "type": "plain_value", 1119 | "named": true 1120 | }, 1121 | { 1122 | "type": "selector_query", 1123 | "named": true 1124 | }, 1125 | { 1126 | "type": "string_value", 1127 | "named": true 1128 | }, 1129 | { 1130 | "type": "unary_query", 1131 | "named": true 1132 | } 1133 | ] 1134 | } 1135 | }, 1136 | { 1137 | "type": "integer_value", 1138 | "named": true, 1139 | "fields": {}, 1140 | "children": { 1141 | "multiple": false, 1142 | "required": false, 1143 | "types": [ 1144 | { 1145 | "type": "unit", 1146 | "named": true 1147 | } 1148 | ] 1149 | } 1150 | }, 1151 | { 1152 | "type": "js_interpolation", 1153 | "named": true, 1154 | "fields": {} 1155 | }, 1156 | { 1157 | "type": "keyframe_block", 1158 | "named": true, 1159 | "fields": {}, 1160 | "children": { 1161 | "multiple": true, 1162 | "required": true, 1163 | "types": [ 1164 | { 1165 | "type": "block", 1166 | "named": true 1167 | }, 1168 | { 1169 | "type": "from", 1170 | "named": true 1171 | }, 1172 | { 1173 | "type": "integer_value", 1174 | "named": true 1175 | }, 1176 | { 1177 | "type": "to", 1178 | "named": true 1179 | } 1180 | ] 1181 | } 1182 | }, 1183 | { 1184 | "type": "keyframe_block_list", 1185 | "named": true, 1186 | "fields": {}, 1187 | "children": { 1188 | "multiple": true, 1189 | "required": false, 1190 | "types": [ 1191 | { 1192 | "type": "keyframe_block", 1193 | "named": true 1194 | } 1195 | ] 1196 | } 1197 | }, 1198 | { 1199 | "type": "keyframes_statement", 1200 | "named": true, 1201 | "fields": {}, 1202 | "children": { 1203 | "multiple": true, 1204 | "required": true, 1205 | "types": [ 1206 | { 1207 | "type": "at_keyword", 1208 | "named": true 1209 | }, 1210 | { 1211 | "type": "keyframe_block_list", 1212 | "named": true 1213 | }, 1214 | { 1215 | "type": "keyframes_name", 1216 | "named": true 1217 | } 1218 | ] 1219 | } 1220 | }, 1221 | { 1222 | "type": "media_statement", 1223 | "named": true, 1224 | "fields": {}, 1225 | "children": { 1226 | "multiple": true, 1227 | "required": true, 1228 | "types": [ 1229 | { 1230 | "type": "binary_query", 1231 | "named": true 1232 | }, 1233 | { 1234 | "type": "block", 1235 | "named": true 1236 | }, 1237 | { 1238 | "type": "feature_query", 1239 | "named": true 1240 | }, 1241 | { 1242 | "type": "keyword_query", 1243 | "named": true 1244 | }, 1245 | { 1246 | "type": "parenthesized_query", 1247 | "named": true 1248 | }, 1249 | { 1250 | "type": "selector_query", 1251 | "named": true 1252 | }, 1253 | { 1254 | "type": "unary_query", 1255 | "named": true 1256 | } 1257 | ] 1258 | } 1259 | }, 1260 | { 1261 | "type": "namespace_selector", 1262 | "named": true, 1263 | "fields": {}, 1264 | "children": { 1265 | "multiple": true, 1266 | "required": true, 1267 | "types": [ 1268 | { 1269 | "type": "adjacent_sibling_selector", 1270 | "named": true 1271 | }, 1272 | { 1273 | "type": "attribute_selector", 1274 | "named": true 1275 | }, 1276 | { 1277 | "type": "child_selector", 1278 | "named": true 1279 | }, 1280 | { 1281 | "type": "class_selector", 1282 | "named": true 1283 | }, 1284 | { 1285 | "type": "descendant_selector", 1286 | "named": true 1287 | }, 1288 | { 1289 | "type": "id_selector", 1290 | "named": true 1291 | }, 1292 | { 1293 | "type": "namespace_selector", 1294 | "named": true 1295 | }, 1296 | { 1297 | "type": "nesting_selector", 1298 | "named": true 1299 | }, 1300 | { 1301 | "type": "pseudo_class_selector", 1302 | "named": true 1303 | }, 1304 | { 1305 | "type": "pseudo_element_selector", 1306 | "named": true 1307 | }, 1308 | { 1309 | "type": "sibling_selector", 1310 | "named": true 1311 | }, 1312 | { 1313 | "type": "string_value", 1314 | "named": true 1315 | }, 1316 | { 1317 | "type": "tag_name", 1318 | "named": true 1319 | }, 1320 | { 1321 | "type": "universal_selector", 1322 | "named": true 1323 | } 1324 | ] 1325 | } 1326 | }, 1327 | { 1328 | "type": "namespace_statement", 1329 | "named": true, 1330 | "fields": {}, 1331 | "children": { 1332 | "multiple": true, 1333 | "required": true, 1334 | "types": [ 1335 | { 1336 | "type": "call_expression", 1337 | "named": true 1338 | }, 1339 | { 1340 | "type": "namespace_name", 1341 | "named": true 1342 | }, 1343 | { 1344 | "type": "string_value", 1345 | "named": true 1346 | } 1347 | ] 1348 | } 1349 | }, 1350 | { 1351 | "type": "parenthesized_query", 1352 | "named": true, 1353 | "fields": {}, 1354 | "children": { 1355 | "multiple": false, 1356 | "required": true, 1357 | "types": [ 1358 | { 1359 | "type": "binary_query", 1360 | "named": true 1361 | }, 1362 | { 1363 | "type": "feature_query", 1364 | "named": true 1365 | }, 1366 | { 1367 | "type": "keyword_query", 1368 | "named": true 1369 | }, 1370 | { 1371 | "type": "parenthesized_query", 1372 | "named": true 1373 | }, 1374 | { 1375 | "type": "selector_query", 1376 | "named": true 1377 | }, 1378 | { 1379 | "type": "unary_query", 1380 | "named": true 1381 | } 1382 | ] 1383 | } 1384 | }, 1385 | { 1386 | "type": "parenthesized_value", 1387 | "named": true, 1388 | "fields": {}, 1389 | "children": { 1390 | "multiple": false, 1391 | "required": true, 1392 | "types": [ 1393 | { 1394 | "type": "binary_expression", 1395 | "named": true 1396 | }, 1397 | { 1398 | "type": "call_expression", 1399 | "named": true 1400 | }, 1401 | { 1402 | "type": "color_value", 1403 | "named": true 1404 | }, 1405 | { 1406 | "type": "float_value", 1407 | "named": true 1408 | }, 1409 | { 1410 | "type": "grid_value", 1411 | "named": true 1412 | }, 1413 | { 1414 | "type": "important", 1415 | "named": true 1416 | }, 1417 | { 1418 | "type": "integer_value", 1419 | "named": true 1420 | }, 1421 | { 1422 | "type": "parenthesized_value", 1423 | "named": true 1424 | }, 1425 | { 1426 | "type": "plain_value", 1427 | "named": true 1428 | }, 1429 | { 1430 | "type": "string_value", 1431 | "named": true 1432 | } 1433 | ] 1434 | } 1435 | }, 1436 | { 1437 | "type": "postcss_statement", 1438 | "named": true, 1439 | "fields": {}, 1440 | "children": { 1441 | "multiple": true, 1442 | "required": true, 1443 | "types": [ 1444 | { 1445 | "type": "at_keyword", 1446 | "named": true 1447 | }, 1448 | { 1449 | "type": "binary_expression", 1450 | "named": true 1451 | }, 1452 | { 1453 | "type": "call_expression", 1454 | "named": true 1455 | }, 1456 | { 1457 | "type": "color_value", 1458 | "named": true 1459 | }, 1460 | { 1461 | "type": "float_value", 1462 | "named": true 1463 | }, 1464 | { 1465 | "type": "grid_value", 1466 | "named": true 1467 | }, 1468 | { 1469 | "type": "important", 1470 | "named": true 1471 | }, 1472 | { 1473 | "type": "integer_value", 1474 | "named": true 1475 | }, 1476 | { 1477 | "type": "parenthesized_value", 1478 | "named": true 1479 | }, 1480 | { 1481 | "type": "plain_value", 1482 | "named": true 1483 | }, 1484 | { 1485 | "type": "string_value", 1486 | "named": true 1487 | } 1488 | ] 1489 | } 1490 | }, 1491 | { 1492 | "type": "pseudo_class_selector", 1493 | "named": true, 1494 | "fields": {}, 1495 | "children": { 1496 | "multiple": true, 1497 | "required": true, 1498 | "types": [ 1499 | { 1500 | "type": "adjacent_sibling_selector", 1501 | "named": true 1502 | }, 1503 | { 1504 | "type": "arguments", 1505 | "named": true 1506 | }, 1507 | { 1508 | "type": "attribute_selector", 1509 | "named": true 1510 | }, 1511 | { 1512 | "type": "child_selector", 1513 | "named": true 1514 | }, 1515 | { 1516 | "type": "class_name", 1517 | "named": true 1518 | }, 1519 | { 1520 | "type": "class_selector", 1521 | "named": true 1522 | }, 1523 | { 1524 | "type": "descendant_selector", 1525 | "named": true 1526 | }, 1527 | { 1528 | "type": "id_selector", 1529 | "named": true 1530 | }, 1531 | { 1532 | "type": "namespace_selector", 1533 | "named": true 1534 | }, 1535 | { 1536 | "type": "nesting_selector", 1537 | "named": true 1538 | }, 1539 | { 1540 | "type": "pseudo_class_selector", 1541 | "named": true 1542 | }, 1543 | { 1544 | "type": "pseudo_element_selector", 1545 | "named": true 1546 | }, 1547 | { 1548 | "type": "sibling_selector", 1549 | "named": true 1550 | }, 1551 | { 1552 | "type": "string_value", 1553 | "named": true 1554 | }, 1555 | { 1556 | "type": "tag_name", 1557 | "named": true 1558 | }, 1559 | { 1560 | "type": "universal_selector", 1561 | "named": true 1562 | } 1563 | ] 1564 | } 1565 | }, 1566 | { 1567 | "type": "pseudo_element_selector", 1568 | "named": true, 1569 | "fields": {}, 1570 | "children": { 1571 | "multiple": true, 1572 | "required": true, 1573 | "types": [ 1574 | { 1575 | "type": "adjacent_sibling_selector", 1576 | "named": true 1577 | }, 1578 | { 1579 | "type": "arguments", 1580 | "named": true 1581 | }, 1582 | { 1583 | "type": "attribute_selector", 1584 | "named": true 1585 | }, 1586 | { 1587 | "type": "child_selector", 1588 | "named": true 1589 | }, 1590 | { 1591 | "type": "class_selector", 1592 | "named": true 1593 | }, 1594 | { 1595 | "type": "descendant_selector", 1596 | "named": true 1597 | }, 1598 | { 1599 | "type": "id_selector", 1600 | "named": true 1601 | }, 1602 | { 1603 | "type": "namespace_selector", 1604 | "named": true 1605 | }, 1606 | { 1607 | "type": "nesting_selector", 1608 | "named": true 1609 | }, 1610 | { 1611 | "type": "pseudo_class_selector", 1612 | "named": true 1613 | }, 1614 | { 1615 | "type": "pseudo_element_selector", 1616 | "named": true 1617 | }, 1618 | { 1619 | "type": "sibling_selector", 1620 | "named": true 1621 | }, 1622 | { 1623 | "type": "string_value", 1624 | "named": true 1625 | }, 1626 | { 1627 | "type": "tag_name", 1628 | "named": true 1629 | }, 1630 | { 1631 | "type": "universal_selector", 1632 | "named": true 1633 | } 1634 | ] 1635 | } 1636 | }, 1637 | { 1638 | "type": "rule_set", 1639 | "named": true, 1640 | "fields": {}, 1641 | "children": { 1642 | "multiple": true, 1643 | "required": true, 1644 | "types": [ 1645 | { 1646 | "type": "block", 1647 | "named": true 1648 | }, 1649 | { 1650 | "type": "selectors", 1651 | "named": true 1652 | } 1653 | ] 1654 | } 1655 | }, 1656 | { 1657 | "type": "selector_query", 1658 | "named": true, 1659 | "fields": {}, 1660 | "children": { 1661 | "multiple": false, 1662 | "required": true, 1663 | "types": [ 1664 | { 1665 | "type": "adjacent_sibling_selector", 1666 | "named": true 1667 | }, 1668 | { 1669 | "type": "attribute_selector", 1670 | "named": true 1671 | }, 1672 | { 1673 | "type": "child_selector", 1674 | "named": true 1675 | }, 1676 | { 1677 | "type": "class_selector", 1678 | "named": true 1679 | }, 1680 | { 1681 | "type": "descendant_selector", 1682 | "named": true 1683 | }, 1684 | { 1685 | "type": "id_selector", 1686 | "named": true 1687 | }, 1688 | { 1689 | "type": "namespace_selector", 1690 | "named": true 1691 | }, 1692 | { 1693 | "type": "nesting_selector", 1694 | "named": true 1695 | }, 1696 | { 1697 | "type": "pseudo_class_selector", 1698 | "named": true 1699 | }, 1700 | { 1701 | "type": "pseudo_element_selector", 1702 | "named": true 1703 | }, 1704 | { 1705 | "type": "sibling_selector", 1706 | "named": true 1707 | }, 1708 | { 1709 | "type": "string_value", 1710 | "named": true 1711 | }, 1712 | { 1713 | "type": "tag_name", 1714 | "named": true 1715 | }, 1716 | { 1717 | "type": "universal_selector", 1718 | "named": true 1719 | } 1720 | ] 1721 | } 1722 | }, 1723 | { 1724 | "type": "selectors", 1725 | "named": true, 1726 | "fields": {}, 1727 | "children": { 1728 | "multiple": true, 1729 | "required": true, 1730 | "types": [ 1731 | { 1732 | "type": "adjacent_sibling_selector", 1733 | "named": true 1734 | }, 1735 | { 1736 | "type": "attribute_selector", 1737 | "named": true 1738 | }, 1739 | { 1740 | "type": "child_selector", 1741 | "named": true 1742 | }, 1743 | { 1744 | "type": "class_selector", 1745 | "named": true 1746 | }, 1747 | { 1748 | "type": "descendant_selector", 1749 | "named": true 1750 | }, 1751 | { 1752 | "type": "id_selector", 1753 | "named": true 1754 | }, 1755 | { 1756 | "type": "namespace_selector", 1757 | "named": true 1758 | }, 1759 | { 1760 | "type": "nesting_selector", 1761 | "named": true 1762 | }, 1763 | { 1764 | "type": "pseudo_class_selector", 1765 | "named": true 1766 | }, 1767 | { 1768 | "type": "pseudo_element_selector", 1769 | "named": true 1770 | }, 1771 | { 1772 | "type": "sibling_selector", 1773 | "named": true 1774 | }, 1775 | { 1776 | "type": "string_value", 1777 | "named": true 1778 | }, 1779 | { 1780 | "type": "tag_name", 1781 | "named": true 1782 | }, 1783 | { 1784 | "type": "universal_selector", 1785 | "named": true 1786 | } 1787 | ] 1788 | } 1789 | }, 1790 | { 1791 | "type": "sibling_selector", 1792 | "named": true, 1793 | "fields": {}, 1794 | "children": { 1795 | "multiple": true, 1796 | "required": true, 1797 | "types": [ 1798 | { 1799 | "type": "adjacent_sibling_selector", 1800 | "named": true 1801 | }, 1802 | { 1803 | "type": "attribute_selector", 1804 | "named": true 1805 | }, 1806 | { 1807 | "type": "child_selector", 1808 | "named": true 1809 | }, 1810 | { 1811 | "type": "class_selector", 1812 | "named": true 1813 | }, 1814 | { 1815 | "type": "descendant_selector", 1816 | "named": true 1817 | }, 1818 | { 1819 | "type": "id_selector", 1820 | "named": true 1821 | }, 1822 | { 1823 | "type": "namespace_selector", 1824 | "named": true 1825 | }, 1826 | { 1827 | "type": "nesting_selector", 1828 | "named": true 1829 | }, 1830 | { 1831 | "type": "pseudo_class_selector", 1832 | "named": true 1833 | }, 1834 | { 1835 | "type": "pseudo_element_selector", 1836 | "named": true 1837 | }, 1838 | { 1839 | "type": "sibling_selector", 1840 | "named": true 1841 | }, 1842 | { 1843 | "type": "string_value", 1844 | "named": true 1845 | }, 1846 | { 1847 | "type": "tag_name", 1848 | "named": true 1849 | }, 1850 | { 1851 | "type": "universal_selector", 1852 | "named": true 1853 | } 1854 | ] 1855 | } 1856 | }, 1857 | { 1858 | "type": "string_value", 1859 | "named": true, 1860 | "fields": {} 1861 | }, 1862 | { 1863 | "type": "stylesheet", 1864 | "named": true, 1865 | "fields": {}, 1866 | "children": { 1867 | "multiple": true, 1868 | "required": false, 1869 | "types": [ 1870 | { 1871 | "type": "at_rule", 1872 | "named": true 1873 | }, 1874 | { 1875 | "type": "charset_statement", 1876 | "named": true 1877 | }, 1878 | { 1879 | "type": "declaration", 1880 | "named": true 1881 | }, 1882 | { 1883 | "type": "import_statement", 1884 | "named": true 1885 | }, 1886 | { 1887 | "type": "js_interpolation", 1888 | "named": true 1889 | }, 1890 | { 1891 | "type": "keyframes_statement", 1892 | "named": true 1893 | }, 1894 | { 1895 | "type": "media_statement", 1896 | "named": true 1897 | }, 1898 | { 1899 | "type": "namespace_statement", 1900 | "named": true 1901 | }, 1902 | { 1903 | "type": "postcss_statement", 1904 | "named": true 1905 | }, 1906 | { 1907 | "type": "rule_set", 1908 | "named": true 1909 | }, 1910 | { 1911 | "type": "supports_statement", 1912 | "named": true 1913 | } 1914 | ] 1915 | } 1916 | }, 1917 | { 1918 | "type": "supports_statement", 1919 | "named": true, 1920 | "fields": {}, 1921 | "children": { 1922 | "multiple": true, 1923 | "required": true, 1924 | "types": [ 1925 | { 1926 | "type": "binary_query", 1927 | "named": true 1928 | }, 1929 | { 1930 | "type": "block", 1931 | "named": true 1932 | }, 1933 | { 1934 | "type": "feature_query", 1935 | "named": true 1936 | }, 1937 | { 1938 | "type": "keyword_query", 1939 | "named": true 1940 | }, 1941 | { 1942 | "type": "parenthesized_query", 1943 | "named": true 1944 | }, 1945 | { 1946 | "type": "selector_query", 1947 | "named": true 1948 | }, 1949 | { 1950 | "type": "unary_query", 1951 | "named": true 1952 | } 1953 | ] 1954 | } 1955 | }, 1956 | { 1957 | "type": "unary_query", 1958 | "named": true, 1959 | "fields": {}, 1960 | "children": { 1961 | "multiple": false, 1962 | "required": true, 1963 | "types": [ 1964 | { 1965 | "type": "binary_query", 1966 | "named": true 1967 | }, 1968 | { 1969 | "type": "feature_query", 1970 | "named": true 1971 | }, 1972 | { 1973 | "type": "keyword_query", 1974 | "named": true 1975 | }, 1976 | { 1977 | "type": "parenthesized_query", 1978 | "named": true 1979 | }, 1980 | { 1981 | "type": "selector_query", 1982 | "named": true 1983 | }, 1984 | { 1985 | "type": "unary_query", 1986 | "named": true 1987 | } 1988 | ] 1989 | } 1990 | }, 1991 | { 1992 | "type": "universal_selector", 1993 | "named": true, 1994 | "fields": {} 1995 | }, 1996 | { 1997 | "type": "\"", 1998 | "named": false 1999 | }, 2000 | { 2001 | "type": "#", 2002 | "named": false 2003 | }, 2004 | { 2005 | "type": "$=", 2006 | "named": false 2007 | }, 2008 | { 2009 | "type": "${", 2010 | "named": false 2011 | }, 2012 | { 2013 | "type": "'", 2014 | "named": false 2015 | }, 2016 | { 2017 | "type": "(", 2018 | "named": false 2019 | }, 2020 | { 2021 | "type": ")", 2022 | "named": false 2023 | }, 2024 | { 2025 | "type": "*", 2026 | "named": false 2027 | }, 2028 | { 2029 | "type": "*=", 2030 | "named": false 2031 | }, 2032 | { 2033 | "type": "+", 2034 | "named": false 2035 | }, 2036 | { 2037 | "type": ",", 2038 | "named": false 2039 | }, 2040 | { 2041 | "type": "-", 2042 | "named": false 2043 | }, 2044 | { 2045 | "type": ".", 2046 | "named": false 2047 | }, 2048 | { 2049 | "type": "/", 2050 | "named": false 2051 | }, 2052 | { 2053 | "type": ":", 2054 | "named": false 2055 | }, 2056 | { 2057 | "type": "::", 2058 | "named": false 2059 | }, 2060 | { 2061 | "type": ";", 2062 | "named": false 2063 | }, 2064 | { 2065 | "type": "=", 2066 | "named": false 2067 | }, 2068 | { 2069 | "type": "=>", 2070 | "named": false 2071 | }, 2072 | { 2073 | "type": ">", 2074 | "named": false 2075 | }, 2076 | { 2077 | "type": "?", 2078 | "named": false 2079 | }, 2080 | { 2081 | "type": "??", 2082 | "named": false 2083 | }, 2084 | { 2085 | "type": "@charset", 2086 | "named": false 2087 | }, 2088 | { 2089 | "type": "@import", 2090 | "named": false 2091 | }, 2092 | { 2093 | "type": "@keyframes", 2094 | "named": false 2095 | }, 2096 | { 2097 | "type": "@media", 2098 | "named": false 2099 | }, 2100 | { 2101 | "type": "@namespace", 2102 | "named": false 2103 | }, 2104 | { 2105 | "type": "@supports", 2106 | "named": false 2107 | }, 2108 | { 2109 | "type": "[", 2110 | "named": false 2111 | }, 2112 | { 2113 | "type": "]", 2114 | "named": false 2115 | }, 2116 | { 2117 | "type": "^=", 2118 | "named": false 2119 | }, 2120 | { 2121 | "type": "and", 2122 | "named": false 2123 | }, 2124 | { 2125 | "type": "at_keyword", 2126 | "named": true 2127 | }, 2128 | { 2129 | "type": "class_name", 2130 | "named": true 2131 | }, 2132 | { 2133 | "type": "comment", 2134 | "named": true 2135 | }, 2136 | { 2137 | "type": "feature_name", 2138 | "named": true 2139 | }, 2140 | { 2141 | "type": "from", 2142 | "named": true 2143 | }, 2144 | { 2145 | "type": "function_name", 2146 | "named": true 2147 | }, 2148 | { 2149 | "type": "id_name", 2150 | "named": true 2151 | }, 2152 | { 2153 | "type": "important", 2154 | "named": true 2155 | }, 2156 | { 2157 | "type": "js_comment", 2158 | "named": true 2159 | }, 2160 | { 2161 | "type": "keyframes_name", 2162 | "named": true 2163 | }, 2164 | { 2165 | "type": "keyword_query", 2166 | "named": true 2167 | }, 2168 | { 2169 | "type": "namespace_name", 2170 | "named": true 2171 | }, 2172 | { 2173 | "type": "nesting_selector", 2174 | "named": true 2175 | }, 2176 | { 2177 | "type": "not", 2178 | "named": false 2179 | }, 2180 | { 2181 | "type": "only", 2182 | "named": false 2183 | }, 2184 | { 2185 | "type": "or", 2186 | "named": false 2187 | }, 2188 | { 2189 | "type": "plain_value", 2190 | "named": true 2191 | }, 2192 | { 2193 | "type": "property_name", 2194 | "named": true 2195 | }, 2196 | { 2197 | "type": "selector", 2198 | "named": false 2199 | }, 2200 | { 2201 | "type": "tag_name", 2202 | "named": true 2203 | }, 2204 | { 2205 | "type": "to", 2206 | "named": true 2207 | }, 2208 | { 2209 | "type": "unit", 2210 | "named": true 2211 | }, 2212 | { 2213 | "type": "{", 2214 | "named": false 2215 | }, 2216 | { 2217 | "type": "|", 2218 | "named": false 2219 | }, 2220 | { 2221 | "type": "|=", 2222 | "named": false 2223 | }, 2224 | { 2225 | "type": "}", 2226 | "named": false 2227 | }, 2228 | { 2229 | "type": "~", 2230 | "named": false 2231 | }, 2232 | { 2233 | "type": "~=", 2234 | "named": false 2235 | } 2236 | ] -------------------------------------------------------------------------------- /src/grammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css_in_js", 3 | "rules": { 4 | "stylesheet": { 5 | "type": "REPEAT", 6 | "content": { 7 | "type": "SYMBOL", 8 | "name": "_top_level_item" 9 | } 10 | }, 11 | "_top_level_item": { 12 | "type": "CHOICE", 13 | "members": [ 14 | { 15 | "type": "CHOICE", 16 | "members": [ 17 | { 18 | "type": "SYMBOL", 19 | "name": "declaration" 20 | }, 21 | { 22 | "type": "SYMBOL", 23 | "name": "rule_set" 24 | }, 25 | { 26 | "type": "SYMBOL", 27 | "name": "import_statement" 28 | }, 29 | { 30 | "type": "SYMBOL", 31 | "name": "media_statement" 32 | }, 33 | { 34 | "type": "SYMBOL", 35 | "name": "charset_statement" 36 | }, 37 | { 38 | "type": "SYMBOL", 39 | "name": "namespace_statement" 40 | }, 41 | { 42 | "type": "SYMBOL", 43 | "name": "keyframes_statement" 44 | }, 45 | { 46 | "type": "SYMBOL", 47 | "name": "supports_statement" 48 | }, 49 | { 50 | "type": "SYMBOL", 51 | "name": "at_rule" 52 | } 53 | ] 54 | }, 55 | { 56 | "type": "SYMBOL", 57 | "name": "_block_item" 58 | }, 59 | { 60 | "type": "SYMBOL", 61 | "name": "js_interpolation" 62 | } 63 | ] 64 | }, 65 | "import_statement": { 66 | "type": "SEQ", 67 | "members": [ 68 | { 69 | "type": "STRING", 70 | "value": "@import" 71 | }, 72 | { 73 | "type": "SYMBOL", 74 | "name": "_value" 75 | }, 76 | { 77 | "type": "CHOICE", 78 | "members": [ 79 | { 80 | "type": "SEQ", 81 | "members": [ 82 | { 83 | "type": "SYMBOL", 84 | "name": "_query" 85 | }, 86 | { 87 | "type": "REPEAT", 88 | "content": { 89 | "type": "SEQ", 90 | "members": [ 91 | { 92 | "type": "STRING", 93 | "value": "," 94 | }, 95 | { 96 | "type": "SYMBOL", 97 | "name": "_query" 98 | } 99 | ] 100 | } 101 | } 102 | ] 103 | }, 104 | { 105 | "type": "BLANK" 106 | } 107 | ] 108 | }, 109 | { 110 | "type": "STRING", 111 | "value": ";" 112 | } 113 | ] 114 | }, 115 | "media_statement": { 116 | "type": "SEQ", 117 | "members": [ 118 | { 119 | "type": "STRING", 120 | "value": "@media" 121 | }, 122 | { 123 | "type": "SEQ", 124 | "members": [ 125 | { 126 | "type": "SYMBOL", 127 | "name": "_query" 128 | }, 129 | { 130 | "type": "REPEAT", 131 | "content": { 132 | "type": "SEQ", 133 | "members": [ 134 | { 135 | "type": "STRING", 136 | "value": "," 137 | }, 138 | { 139 | "type": "SYMBOL", 140 | "name": "_query" 141 | } 142 | ] 143 | } 144 | } 145 | ] 146 | }, 147 | { 148 | "type": "SYMBOL", 149 | "name": "block" 150 | } 151 | ] 152 | }, 153 | "charset_statement": { 154 | "type": "SEQ", 155 | "members": [ 156 | { 157 | "type": "STRING", 158 | "value": "@charset" 159 | }, 160 | { 161 | "type": "SYMBOL", 162 | "name": "_value" 163 | }, 164 | { 165 | "type": "STRING", 166 | "value": ";" 167 | } 168 | ] 169 | }, 170 | "namespace_statement": { 171 | "type": "SEQ", 172 | "members": [ 173 | { 174 | "type": "STRING", 175 | "value": "@namespace" 176 | }, 177 | { 178 | "type": "CHOICE", 179 | "members": [ 180 | { 181 | "type": "ALIAS", 182 | "content": { 183 | "type": "SYMBOL", 184 | "name": "identifier" 185 | }, 186 | "named": true, 187 | "value": "namespace_name" 188 | }, 189 | { 190 | "type": "BLANK" 191 | } 192 | ] 193 | }, 194 | { 195 | "type": "CHOICE", 196 | "members": [ 197 | { 198 | "type": "SYMBOL", 199 | "name": "string_value" 200 | }, 201 | { 202 | "type": "SYMBOL", 203 | "name": "call_expression" 204 | } 205 | ] 206 | }, 207 | { 208 | "type": "STRING", 209 | "value": ";" 210 | } 211 | ] 212 | }, 213 | "keyframes_statement": { 214 | "type": "SEQ", 215 | "members": [ 216 | { 217 | "type": "CHOICE", 218 | "members": [ 219 | { 220 | "type": "STRING", 221 | "value": "@keyframes" 222 | }, 223 | { 224 | "type": "ALIAS", 225 | "content": { 226 | "type": "PATTERN", 227 | "value": "@[-a-z]+keyframes" 228 | }, 229 | "named": true, 230 | "value": "at_keyword" 231 | } 232 | ] 233 | }, 234 | { 235 | "type": "ALIAS", 236 | "content": { 237 | "type": "SYMBOL", 238 | "name": "identifier" 239 | }, 240 | "named": true, 241 | "value": "keyframes_name" 242 | }, 243 | { 244 | "type": "SYMBOL", 245 | "name": "keyframe_block_list" 246 | } 247 | ] 248 | }, 249 | "keyframe_block_list": { 250 | "type": "SEQ", 251 | "members": [ 252 | { 253 | "type": "STRING", 254 | "value": "{" 255 | }, 256 | { 257 | "type": "REPEAT", 258 | "content": { 259 | "type": "SYMBOL", 260 | "name": "keyframe_block" 261 | } 262 | }, 263 | { 264 | "type": "STRING", 265 | "value": "}" 266 | } 267 | ] 268 | }, 269 | "keyframe_block": { 270 | "type": "SEQ", 271 | "members": [ 272 | { 273 | "type": "CHOICE", 274 | "members": [ 275 | { 276 | "type": "SYMBOL", 277 | "name": "from" 278 | }, 279 | { 280 | "type": "SYMBOL", 281 | "name": "to" 282 | }, 283 | { 284 | "type": "SYMBOL", 285 | "name": "integer_value" 286 | } 287 | ] 288 | }, 289 | { 290 | "type": "SYMBOL", 291 | "name": "block" 292 | } 293 | ] 294 | }, 295 | "from": { 296 | "type": "STRING", 297 | "value": "from" 298 | }, 299 | "to": { 300 | "type": "STRING", 301 | "value": "to" 302 | }, 303 | "supports_statement": { 304 | "type": "SEQ", 305 | "members": [ 306 | { 307 | "type": "STRING", 308 | "value": "@supports" 309 | }, 310 | { 311 | "type": "SYMBOL", 312 | "name": "_query" 313 | }, 314 | { 315 | "type": "SYMBOL", 316 | "name": "block" 317 | } 318 | ] 319 | }, 320 | "postcss_statement": { 321 | "type": "PREC", 322 | "value": -1, 323 | "content": { 324 | "type": "SEQ", 325 | "members": [ 326 | { 327 | "type": "SYMBOL", 328 | "name": "at_keyword" 329 | }, 330 | { 331 | "type": "REPEAT", 332 | "content": { 333 | "type": "SYMBOL", 334 | "name": "_value" 335 | } 336 | }, 337 | { 338 | "type": "STRING", 339 | "value": ";" 340 | } 341 | ] 342 | } 343 | }, 344 | "at_rule": { 345 | "type": "SEQ", 346 | "members": [ 347 | { 348 | "type": "SYMBOL", 349 | "name": "at_keyword" 350 | }, 351 | { 352 | "type": "CHOICE", 353 | "members": [ 354 | { 355 | "type": "SEQ", 356 | "members": [ 357 | { 358 | "type": "SYMBOL", 359 | "name": "_query" 360 | }, 361 | { 362 | "type": "REPEAT", 363 | "content": { 364 | "type": "SEQ", 365 | "members": [ 366 | { 367 | "type": "STRING", 368 | "value": "," 369 | }, 370 | { 371 | "type": "SYMBOL", 372 | "name": "_query" 373 | } 374 | ] 375 | } 376 | } 377 | ] 378 | }, 379 | { 380 | "type": "BLANK" 381 | } 382 | ] 383 | }, 384 | { 385 | "type": "CHOICE", 386 | "members": [ 387 | { 388 | "type": "STRING", 389 | "value": ";" 390 | }, 391 | { 392 | "type": "SYMBOL", 393 | "name": "block" 394 | } 395 | ] 396 | } 397 | ] 398 | }, 399 | "rule_set": { 400 | "type": "SEQ", 401 | "members": [ 402 | { 403 | "type": "SYMBOL", 404 | "name": "selectors" 405 | }, 406 | { 407 | "type": "SYMBOL", 408 | "name": "block" 409 | } 410 | ] 411 | }, 412 | "selectors": { 413 | "type": "SEQ", 414 | "members": [ 415 | { 416 | "type": "SYMBOL", 417 | "name": "_selector" 418 | }, 419 | { 420 | "type": "REPEAT", 421 | "content": { 422 | "type": "SEQ", 423 | "members": [ 424 | { 425 | "type": "STRING", 426 | "value": "," 427 | }, 428 | { 429 | "type": "SYMBOL", 430 | "name": "_selector" 431 | } 432 | ] 433 | } 434 | } 435 | ] 436 | }, 437 | "block": { 438 | "type": "SEQ", 439 | "members": [ 440 | { 441 | "type": "STRING", 442 | "value": "{" 443 | }, 444 | { 445 | "type": "REPEAT", 446 | "content": { 447 | "type": "SYMBOL", 448 | "name": "_block_item" 449 | } 450 | }, 451 | { 452 | "type": "CHOICE", 453 | "members": [ 454 | { 455 | "type": "ALIAS", 456 | "content": { 457 | "type": "SYMBOL", 458 | "name": "last_declaration" 459 | }, 460 | "named": true, 461 | "value": "declaration" 462 | }, 463 | { 464 | "type": "BLANK" 465 | } 466 | ] 467 | }, 468 | { 469 | "type": "STRING", 470 | "value": "}" 471 | } 472 | ] 473 | }, 474 | "_block_item": { 475 | "type": "CHOICE", 476 | "members": [ 477 | { 478 | "type": "CHOICE", 479 | "members": [ 480 | { 481 | "type": "SYMBOL", 482 | "name": "declaration" 483 | }, 484 | { 485 | "type": "SYMBOL", 486 | "name": "rule_set" 487 | }, 488 | { 489 | "type": "SYMBOL", 490 | "name": "import_statement" 491 | }, 492 | { 493 | "type": "SYMBOL", 494 | "name": "media_statement" 495 | }, 496 | { 497 | "type": "SYMBOL", 498 | "name": "charset_statement" 499 | }, 500 | { 501 | "type": "SYMBOL", 502 | "name": "namespace_statement" 503 | }, 504 | { 505 | "type": "SYMBOL", 506 | "name": "keyframes_statement" 507 | }, 508 | { 509 | "type": "SYMBOL", 510 | "name": "supports_statement" 511 | }, 512 | { 513 | "type": "SYMBOL", 514 | "name": "postcss_statement" 515 | }, 516 | { 517 | "type": "SYMBOL", 518 | "name": "at_rule" 519 | } 520 | ] 521 | }, 522 | { 523 | "type": "SEQ", 524 | "members": [ 525 | { 526 | "type": "SYMBOL", 527 | "name": "js_interpolation" 528 | }, 529 | { 530 | "type": "CHOICE", 531 | "members": [ 532 | { 533 | "type": "STRING", 534 | "value": ";" 535 | }, 536 | { 537 | "type": "BLANK" 538 | } 539 | ] 540 | } 541 | ] 542 | } 543 | ] 544 | }, 545 | "_selector": { 546 | "type": "CHOICE", 547 | "members": [ 548 | { 549 | "type": "SYMBOL", 550 | "name": "universal_selector" 551 | }, 552 | { 553 | "type": "ALIAS", 554 | "content": { 555 | "type": "SYMBOL", 556 | "name": "identifier" 557 | }, 558 | "named": true, 559 | "value": "tag_name" 560 | }, 561 | { 562 | "type": "SYMBOL", 563 | "name": "class_selector" 564 | }, 565 | { 566 | "type": "SYMBOL", 567 | "name": "nesting_selector" 568 | }, 569 | { 570 | "type": "SYMBOL", 571 | "name": "pseudo_class_selector" 572 | }, 573 | { 574 | "type": "SYMBOL", 575 | "name": "pseudo_element_selector" 576 | }, 577 | { 578 | "type": "SYMBOL", 579 | "name": "id_selector" 580 | }, 581 | { 582 | "type": "SYMBOL", 583 | "name": "attribute_selector" 584 | }, 585 | { 586 | "type": "SYMBOL", 587 | "name": "string_value" 588 | }, 589 | { 590 | "type": "SYMBOL", 591 | "name": "child_selector" 592 | }, 593 | { 594 | "type": "SYMBOL", 595 | "name": "descendant_selector" 596 | }, 597 | { 598 | "type": "SYMBOL", 599 | "name": "sibling_selector" 600 | }, 601 | { 602 | "type": "SYMBOL", 603 | "name": "adjacent_sibling_selector" 604 | }, 605 | { 606 | "type": "SYMBOL", 607 | "name": "namespace_selector" 608 | } 609 | ] 610 | }, 611 | "nesting_selector": { 612 | "type": "STRING", 613 | "value": "&" 614 | }, 615 | "universal_selector": { 616 | "type": "STRING", 617 | "value": "*" 618 | }, 619 | "class_selector": { 620 | "type": "PREC", 621 | "value": 1, 622 | "content": { 623 | "type": "SEQ", 624 | "members": [ 625 | { 626 | "type": "CHOICE", 627 | "members": [ 628 | { 629 | "type": "SYMBOL", 630 | "name": "_selector" 631 | }, 632 | { 633 | "type": "BLANK" 634 | } 635 | ] 636 | }, 637 | { 638 | "type": "STRING", 639 | "value": "." 640 | }, 641 | { 642 | "type": "ALIAS", 643 | "content": { 644 | "type": "SYMBOL", 645 | "name": "identifier" 646 | }, 647 | "named": true, 648 | "value": "class_name" 649 | } 650 | ] 651 | } 652 | }, 653 | "pseudo_class_selector": { 654 | "type": "SEQ", 655 | "members": [ 656 | { 657 | "type": "CHOICE", 658 | "members": [ 659 | { 660 | "type": "SYMBOL", 661 | "name": "_selector" 662 | }, 663 | { 664 | "type": "BLANK" 665 | } 666 | ] 667 | }, 668 | { 669 | "type": "ALIAS", 670 | "content": { 671 | "type": "SYMBOL", 672 | "name": "_pseudo_class_selector_colon" 673 | }, 674 | "named": false, 675 | "value": ":" 676 | }, 677 | { 678 | "type": "ALIAS", 679 | "content": { 680 | "type": "SYMBOL", 681 | "name": "identifier" 682 | }, 683 | "named": true, 684 | "value": "class_name" 685 | }, 686 | { 687 | "type": "CHOICE", 688 | "members": [ 689 | { 690 | "type": "ALIAS", 691 | "content": { 692 | "type": "SYMBOL", 693 | "name": "pseudo_class_arguments" 694 | }, 695 | "named": true, 696 | "value": "arguments" 697 | }, 698 | { 699 | "type": "BLANK" 700 | } 701 | ] 702 | } 703 | ] 704 | }, 705 | "pseudo_element_selector": { 706 | "type": "SEQ", 707 | "members": [ 708 | { 709 | "type": "CHOICE", 710 | "members": [ 711 | { 712 | "type": "SYMBOL", 713 | "name": "_selector" 714 | }, 715 | { 716 | "type": "BLANK" 717 | } 718 | ] 719 | }, 720 | { 721 | "type": "STRING", 722 | "value": "::" 723 | }, 724 | { 725 | "type": "ALIAS", 726 | "content": { 727 | "type": "SYMBOL", 728 | "name": "identifier" 729 | }, 730 | "named": true, 731 | "value": "tag_name" 732 | }, 733 | { 734 | "type": "CHOICE", 735 | "members": [ 736 | { 737 | "type": "ALIAS", 738 | "content": { 739 | "type": "SYMBOL", 740 | "name": "pseudo_element_arguments" 741 | }, 742 | "named": true, 743 | "value": "arguments" 744 | }, 745 | { 746 | "type": "BLANK" 747 | } 748 | ] 749 | } 750 | ] 751 | }, 752 | "id_selector": { 753 | "type": "SEQ", 754 | "members": [ 755 | { 756 | "type": "CHOICE", 757 | "members": [ 758 | { 759 | "type": "SYMBOL", 760 | "name": "_selector" 761 | }, 762 | { 763 | "type": "BLANK" 764 | } 765 | ] 766 | }, 767 | { 768 | "type": "STRING", 769 | "value": "#" 770 | }, 771 | { 772 | "type": "ALIAS", 773 | "content": { 774 | "type": "SYMBOL", 775 | "name": "identifier" 776 | }, 777 | "named": true, 778 | "value": "id_name" 779 | } 780 | ] 781 | }, 782 | "attribute_selector": { 783 | "type": "SEQ", 784 | "members": [ 785 | { 786 | "type": "CHOICE", 787 | "members": [ 788 | { 789 | "type": "SYMBOL", 790 | "name": "_selector" 791 | }, 792 | { 793 | "type": "BLANK" 794 | } 795 | ] 796 | }, 797 | { 798 | "type": "STRING", 799 | "value": "[" 800 | }, 801 | { 802 | "type": "ALIAS", 803 | "content": { 804 | "type": "CHOICE", 805 | "members": [ 806 | { 807 | "type": "SYMBOL", 808 | "name": "identifier" 809 | }, 810 | { 811 | "type": "SYMBOL", 812 | "name": "namespace_selector" 813 | } 814 | ] 815 | }, 816 | "named": true, 817 | "value": "attribute_name" 818 | }, 819 | { 820 | "type": "CHOICE", 821 | "members": [ 822 | { 823 | "type": "SEQ", 824 | "members": [ 825 | { 826 | "type": "CHOICE", 827 | "members": [ 828 | { 829 | "type": "STRING", 830 | "value": "=" 831 | }, 832 | { 833 | "type": "STRING", 834 | "value": "~=" 835 | }, 836 | { 837 | "type": "STRING", 838 | "value": "^=" 839 | }, 840 | { 841 | "type": "STRING", 842 | "value": "|=" 843 | }, 844 | { 845 | "type": "STRING", 846 | "value": "*=" 847 | }, 848 | { 849 | "type": "STRING", 850 | "value": "$=" 851 | } 852 | ] 853 | }, 854 | { 855 | "type": "SYMBOL", 856 | "name": "_value" 857 | } 858 | ] 859 | }, 860 | { 861 | "type": "BLANK" 862 | } 863 | ] 864 | }, 865 | { 866 | "type": "STRING", 867 | "value": "]" 868 | } 869 | ] 870 | }, 871 | "child_selector": { 872 | "type": "PREC_LEFT", 873 | "value": 0, 874 | "content": { 875 | "type": "SEQ", 876 | "members": [ 877 | { 878 | "type": "SYMBOL", 879 | "name": "_selector" 880 | }, 881 | { 882 | "type": "STRING", 883 | "value": ">" 884 | }, 885 | { 886 | "type": "SYMBOL", 887 | "name": "_selector" 888 | } 889 | ] 890 | } 891 | }, 892 | "descendant_selector": { 893 | "type": "PREC_LEFT", 894 | "value": 0, 895 | "content": { 896 | "type": "SEQ", 897 | "members": [ 898 | { 899 | "type": "SYMBOL", 900 | "name": "_selector" 901 | }, 902 | { 903 | "type": "SYMBOL", 904 | "name": "_descendant_operator" 905 | }, 906 | { 907 | "type": "SYMBOL", 908 | "name": "_selector" 909 | } 910 | ] 911 | } 912 | }, 913 | "sibling_selector": { 914 | "type": "PREC_LEFT", 915 | "value": 0, 916 | "content": { 917 | "type": "SEQ", 918 | "members": [ 919 | { 920 | "type": "SYMBOL", 921 | "name": "_selector" 922 | }, 923 | { 924 | "type": "STRING", 925 | "value": "~" 926 | }, 927 | { 928 | "type": "SYMBOL", 929 | "name": "_selector" 930 | } 931 | ] 932 | } 933 | }, 934 | "adjacent_sibling_selector": { 935 | "type": "PREC_LEFT", 936 | "value": 0, 937 | "content": { 938 | "type": "SEQ", 939 | "members": [ 940 | { 941 | "type": "SYMBOL", 942 | "name": "_selector" 943 | }, 944 | { 945 | "type": "STRING", 946 | "value": "+" 947 | }, 948 | { 949 | "type": "SYMBOL", 950 | "name": "_selector" 951 | } 952 | ] 953 | } 954 | }, 955 | "namespace_selector": { 956 | "type": "PREC_LEFT", 957 | "value": 0, 958 | "content": { 959 | "type": "SEQ", 960 | "members": [ 961 | { 962 | "type": "SYMBOL", 963 | "name": "_selector" 964 | }, 965 | { 966 | "type": "STRING", 967 | "value": "|" 968 | }, 969 | { 970 | "type": "SYMBOL", 971 | "name": "_selector" 972 | } 973 | ] 974 | } 975 | }, 976 | "pseudo_class_arguments": { 977 | "type": "SEQ", 978 | "members": [ 979 | { 980 | "type": "IMMEDIATE_TOKEN", 981 | "content": { 982 | "type": "STRING", 983 | "value": "(" 984 | } 985 | }, 986 | { 987 | "type": "CHOICE", 988 | "members": [ 989 | { 990 | "type": "SEQ", 991 | "members": [ 992 | { 993 | "type": "CHOICE", 994 | "members": [ 995 | { 996 | "type": "SYMBOL", 997 | "name": "_selector" 998 | }, 999 | { 1000 | "type": "REPEAT1", 1001 | "content": { 1002 | "type": "SYMBOL", 1003 | "name": "_value" 1004 | } 1005 | } 1006 | ] 1007 | }, 1008 | { 1009 | "type": "REPEAT", 1010 | "content": { 1011 | "type": "SEQ", 1012 | "members": [ 1013 | { 1014 | "type": "STRING", 1015 | "value": "," 1016 | }, 1017 | { 1018 | "type": "CHOICE", 1019 | "members": [ 1020 | { 1021 | "type": "SYMBOL", 1022 | "name": "_selector" 1023 | }, 1024 | { 1025 | "type": "REPEAT1", 1026 | "content": { 1027 | "type": "SYMBOL", 1028 | "name": "_value" 1029 | } 1030 | } 1031 | ] 1032 | } 1033 | ] 1034 | } 1035 | } 1036 | ] 1037 | }, 1038 | { 1039 | "type": "BLANK" 1040 | } 1041 | ] 1042 | }, 1043 | { 1044 | "type": "STRING", 1045 | "value": ")" 1046 | } 1047 | ] 1048 | }, 1049 | "pseudo_element_arguments": { 1050 | "type": "SEQ", 1051 | "members": [ 1052 | { 1053 | "type": "IMMEDIATE_TOKEN", 1054 | "content": { 1055 | "type": "STRING", 1056 | "value": "(" 1057 | } 1058 | }, 1059 | { 1060 | "type": "CHOICE", 1061 | "members": [ 1062 | { 1063 | "type": "SEQ", 1064 | "members": [ 1065 | { 1066 | "type": "CHOICE", 1067 | "members": [ 1068 | { 1069 | "type": "SYMBOL", 1070 | "name": "_selector" 1071 | }, 1072 | { 1073 | "type": "REPEAT1", 1074 | "content": { 1075 | "type": "SYMBOL", 1076 | "name": "_value" 1077 | } 1078 | } 1079 | ] 1080 | }, 1081 | { 1082 | "type": "REPEAT", 1083 | "content": { 1084 | "type": "SEQ", 1085 | "members": [ 1086 | { 1087 | "type": "STRING", 1088 | "value": "," 1089 | }, 1090 | { 1091 | "type": "CHOICE", 1092 | "members": [ 1093 | { 1094 | "type": "SYMBOL", 1095 | "name": "_selector" 1096 | }, 1097 | { 1098 | "type": "REPEAT1", 1099 | "content": { 1100 | "type": "SYMBOL", 1101 | "name": "_value" 1102 | } 1103 | } 1104 | ] 1105 | } 1106 | ] 1107 | } 1108 | } 1109 | ] 1110 | }, 1111 | { 1112 | "type": "BLANK" 1113 | } 1114 | ] 1115 | }, 1116 | { 1117 | "type": "STRING", 1118 | "value": ")" 1119 | } 1120 | ] 1121 | }, 1122 | "declaration": { 1123 | "type": "CHOICE", 1124 | "members": [ 1125 | { 1126 | "type": "SEQ", 1127 | "members": [ 1128 | { 1129 | "type": "ALIAS", 1130 | "content": { 1131 | "type": "SYMBOL", 1132 | "name": "identifier" 1133 | }, 1134 | "named": true, 1135 | "value": "property_name" 1136 | }, 1137 | { 1138 | "type": "STRING", 1139 | "value": ":" 1140 | }, 1141 | { 1142 | "type": "SYMBOL", 1143 | "name": "_value" 1144 | }, 1145 | { 1146 | "type": "REPEAT", 1147 | "content": { 1148 | "type": "SEQ", 1149 | "members": [ 1150 | { 1151 | "type": "CHOICE", 1152 | "members": [ 1153 | { 1154 | "type": "STRING", 1155 | "value": "," 1156 | }, 1157 | { 1158 | "type": "BLANK" 1159 | } 1160 | ] 1161 | }, 1162 | { 1163 | "type": "SYMBOL", 1164 | "name": "_value" 1165 | } 1166 | ] 1167 | } 1168 | }, 1169 | { 1170 | "type": "CHOICE", 1171 | "members": [ 1172 | { 1173 | "type": "SYMBOL", 1174 | "name": "important" 1175 | }, 1176 | { 1177 | "type": "BLANK" 1178 | } 1179 | ] 1180 | }, 1181 | { 1182 | "type": "STRING", 1183 | "value": ";" 1184 | } 1185 | ] 1186 | }, 1187 | { 1188 | "type": "SEQ", 1189 | "members": [ 1190 | { 1191 | "type": "ALIAS", 1192 | "content": { 1193 | "type": "SYMBOL", 1194 | "name": "identifier" 1195 | }, 1196 | "named": true, 1197 | "value": "property_name" 1198 | }, 1199 | { 1200 | "type": "STRING", 1201 | "value": ":" 1202 | }, 1203 | { 1204 | "type": "SYMBOL", 1205 | "name": "js_interpolation" 1206 | }, 1207 | { 1208 | "type": "REPEAT", 1209 | "content": { 1210 | "type": "SEQ", 1211 | "members": [ 1212 | { 1213 | "type": "CHOICE", 1214 | "members": [ 1215 | { 1216 | "type": "STRING", 1217 | "value": "," 1218 | }, 1219 | { 1220 | "type": "BLANK" 1221 | } 1222 | ] 1223 | }, 1224 | { 1225 | "type": "SYMBOL", 1226 | "name": "_value" 1227 | } 1228 | ] 1229 | } 1230 | }, 1231 | { 1232 | "type": "CHOICE", 1233 | "members": [ 1234 | { 1235 | "type": "SYMBOL", 1236 | "name": "important" 1237 | }, 1238 | { 1239 | "type": "BLANK" 1240 | } 1241 | ] 1242 | }, 1243 | { 1244 | "type": "STRING", 1245 | "value": ";" 1246 | } 1247 | ] 1248 | } 1249 | ] 1250 | }, 1251 | "last_declaration": { 1252 | "type": "PREC", 1253 | "value": 1, 1254 | "content": { 1255 | "type": "SEQ", 1256 | "members": [ 1257 | { 1258 | "type": "ALIAS", 1259 | "content": { 1260 | "type": "SYMBOL", 1261 | "name": "identifier" 1262 | }, 1263 | "named": true, 1264 | "value": "property_name" 1265 | }, 1266 | { 1267 | "type": "STRING", 1268 | "value": ":" 1269 | }, 1270 | { 1271 | "type": "SYMBOL", 1272 | "name": "_value" 1273 | }, 1274 | { 1275 | "type": "REPEAT", 1276 | "content": { 1277 | "type": "SEQ", 1278 | "members": [ 1279 | { 1280 | "type": "CHOICE", 1281 | "members": [ 1282 | { 1283 | "type": "STRING", 1284 | "value": "," 1285 | }, 1286 | { 1287 | "type": "BLANK" 1288 | } 1289 | ] 1290 | }, 1291 | { 1292 | "type": "SYMBOL", 1293 | "name": "_value" 1294 | } 1295 | ] 1296 | } 1297 | }, 1298 | { 1299 | "type": "CHOICE", 1300 | "members": [ 1301 | { 1302 | "type": "SYMBOL", 1303 | "name": "important" 1304 | }, 1305 | { 1306 | "type": "BLANK" 1307 | } 1308 | ] 1309 | } 1310 | ] 1311 | } 1312 | }, 1313 | "important": { 1314 | "type": "STRING", 1315 | "value": "!important" 1316 | }, 1317 | "_query": { 1318 | "type": "CHOICE", 1319 | "members": [ 1320 | { 1321 | "type": "ALIAS", 1322 | "content": { 1323 | "type": "SYMBOL", 1324 | "name": "identifier" 1325 | }, 1326 | "named": true, 1327 | "value": "keyword_query" 1328 | }, 1329 | { 1330 | "type": "SYMBOL", 1331 | "name": "feature_query" 1332 | }, 1333 | { 1334 | "type": "SYMBOL", 1335 | "name": "binary_query" 1336 | }, 1337 | { 1338 | "type": "SYMBOL", 1339 | "name": "unary_query" 1340 | }, 1341 | { 1342 | "type": "SYMBOL", 1343 | "name": "selector_query" 1344 | }, 1345 | { 1346 | "type": "SYMBOL", 1347 | "name": "parenthesized_query" 1348 | } 1349 | ] 1350 | }, 1351 | "feature_query": { 1352 | "type": "SEQ", 1353 | "members": [ 1354 | { 1355 | "type": "STRING", 1356 | "value": "(" 1357 | }, 1358 | { 1359 | "type": "ALIAS", 1360 | "content": { 1361 | "type": "SYMBOL", 1362 | "name": "identifier" 1363 | }, 1364 | "named": true, 1365 | "value": "feature_name" 1366 | }, 1367 | { 1368 | "type": "STRING", 1369 | "value": ":" 1370 | }, 1371 | { 1372 | "type": "REPEAT1", 1373 | "content": { 1374 | "type": "SYMBOL", 1375 | "name": "_value" 1376 | } 1377 | }, 1378 | { 1379 | "type": "STRING", 1380 | "value": ")" 1381 | } 1382 | ] 1383 | }, 1384 | "parenthesized_query": { 1385 | "type": "SEQ", 1386 | "members": [ 1387 | { 1388 | "type": "STRING", 1389 | "value": "(" 1390 | }, 1391 | { 1392 | "type": "SYMBOL", 1393 | "name": "_query" 1394 | }, 1395 | { 1396 | "type": "STRING", 1397 | "value": ")" 1398 | } 1399 | ] 1400 | }, 1401 | "binary_query": { 1402 | "type": "PREC_LEFT", 1403 | "value": 0, 1404 | "content": { 1405 | "type": "SEQ", 1406 | "members": [ 1407 | { 1408 | "type": "SYMBOL", 1409 | "name": "_query" 1410 | }, 1411 | { 1412 | "type": "CHOICE", 1413 | "members": [ 1414 | { 1415 | "type": "STRING", 1416 | "value": "and" 1417 | }, 1418 | { 1419 | "type": "STRING", 1420 | "value": "or" 1421 | } 1422 | ] 1423 | }, 1424 | { 1425 | "type": "SYMBOL", 1426 | "name": "_query" 1427 | } 1428 | ] 1429 | } 1430 | }, 1431 | "unary_query": { 1432 | "type": "PREC", 1433 | "value": 1, 1434 | "content": { 1435 | "type": "SEQ", 1436 | "members": [ 1437 | { 1438 | "type": "CHOICE", 1439 | "members": [ 1440 | { 1441 | "type": "STRING", 1442 | "value": "not" 1443 | }, 1444 | { 1445 | "type": "STRING", 1446 | "value": "only" 1447 | } 1448 | ] 1449 | }, 1450 | { 1451 | "type": "SYMBOL", 1452 | "name": "_query" 1453 | } 1454 | ] 1455 | } 1456 | }, 1457 | "selector_query": { 1458 | "type": "SEQ", 1459 | "members": [ 1460 | { 1461 | "type": "STRING", 1462 | "value": "selector" 1463 | }, 1464 | { 1465 | "type": "STRING", 1466 | "value": "(" 1467 | }, 1468 | { 1469 | "type": "SYMBOL", 1470 | "name": "_selector" 1471 | }, 1472 | { 1473 | "type": "STRING", 1474 | "value": ")" 1475 | } 1476 | ] 1477 | }, 1478 | "_value": { 1479 | "type": "PREC", 1480 | "value": -1, 1481 | "content": { 1482 | "type": "CHOICE", 1483 | "members": [ 1484 | { 1485 | "type": "ALIAS", 1486 | "content": { 1487 | "type": "SYMBOL", 1488 | "name": "identifier" 1489 | }, 1490 | "named": true, 1491 | "value": "plain_value" 1492 | }, 1493 | { 1494 | "type": "SYMBOL", 1495 | "name": "plain_value" 1496 | }, 1497 | { 1498 | "type": "SYMBOL", 1499 | "name": "color_value" 1500 | }, 1501 | { 1502 | "type": "SYMBOL", 1503 | "name": "integer_value" 1504 | }, 1505 | { 1506 | "type": "SYMBOL", 1507 | "name": "float_value" 1508 | }, 1509 | { 1510 | "type": "SYMBOL", 1511 | "name": "string_value" 1512 | }, 1513 | { 1514 | "type": "SYMBOL", 1515 | "name": "grid_value" 1516 | }, 1517 | { 1518 | "type": "SYMBOL", 1519 | "name": "binary_expression" 1520 | }, 1521 | { 1522 | "type": "SYMBOL", 1523 | "name": "parenthesized_value" 1524 | }, 1525 | { 1526 | "type": "SYMBOL", 1527 | "name": "call_expression" 1528 | }, 1529 | { 1530 | "type": "SYMBOL", 1531 | "name": "important" 1532 | } 1533 | ] 1534 | } 1535 | }, 1536 | "parenthesized_value": { 1537 | "type": "SEQ", 1538 | "members": [ 1539 | { 1540 | "type": "STRING", 1541 | "value": "(" 1542 | }, 1543 | { 1544 | "type": "SYMBOL", 1545 | "name": "_value" 1546 | }, 1547 | { 1548 | "type": "STRING", 1549 | "value": ")" 1550 | } 1551 | ] 1552 | }, 1553 | "color_value": { 1554 | "type": "SEQ", 1555 | "members": [ 1556 | { 1557 | "type": "STRING", 1558 | "value": "#" 1559 | }, 1560 | { 1561 | "type": "IMMEDIATE_TOKEN", 1562 | "content": { 1563 | "type": "PATTERN", 1564 | "value": "[0-9a-fA-F]{3,8}" 1565 | } 1566 | } 1567 | ] 1568 | }, 1569 | "string_value": { 1570 | "type": "CHOICE", 1571 | "members": [ 1572 | { 1573 | "type": "SEQ", 1574 | "members": [ 1575 | { 1576 | "type": "STRING", 1577 | "value": "'" 1578 | }, 1579 | { 1580 | "type": "PATTERN", 1581 | "value": "([^'\\n]|\\\\(.|\\n))*" 1582 | }, 1583 | { 1584 | "type": "STRING", 1585 | "value": "'" 1586 | } 1587 | ] 1588 | }, 1589 | { 1590 | "type": "SEQ", 1591 | "members": [ 1592 | { 1593 | "type": "STRING", 1594 | "value": "\"" 1595 | }, 1596 | { 1597 | "type": "PATTERN", 1598 | "value": "([^\"\\n]|\\\\(.|\\n))*" 1599 | }, 1600 | { 1601 | "type": "STRING", 1602 | "value": "\"" 1603 | } 1604 | ] 1605 | } 1606 | ] 1607 | }, 1608 | "integer_value": { 1609 | "type": "SEQ", 1610 | "members": [ 1611 | { 1612 | "type": "TOKEN", 1613 | "content": { 1614 | "type": "SEQ", 1615 | "members": [ 1616 | { 1617 | "type": "CHOICE", 1618 | "members": [ 1619 | { 1620 | "type": "CHOICE", 1621 | "members": [ 1622 | { 1623 | "type": "STRING", 1624 | "value": "+" 1625 | }, 1626 | { 1627 | "type": "STRING", 1628 | "value": "-" 1629 | } 1630 | ] 1631 | }, 1632 | { 1633 | "type": "BLANK" 1634 | } 1635 | ] 1636 | }, 1637 | { 1638 | "type": "PATTERN", 1639 | "value": "\\d+" 1640 | } 1641 | ] 1642 | } 1643 | }, 1644 | { 1645 | "type": "CHOICE", 1646 | "members": [ 1647 | { 1648 | "type": "SYMBOL", 1649 | "name": "unit" 1650 | }, 1651 | { 1652 | "type": "BLANK" 1653 | } 1654 | ] 1655 | } 1656 | ] 1657 | }, 1658 | "float_value": { 1659 | "type": "SEQ", 1660 | "members": [ 1661 | { 1662 | "type": "TOKEN", 1663 | "content": { 1664 | "type": "SEQ", 1665 | "members": [ 1666 | { 1667 | "type": "CHOICE", 1668 | "members": [ 1669 | { 1670 | "type": "CHOICE", 1671 | "members": [ 1672 | { 1673 | "type": "STRING", 1674 | "value": "+" 1675 | }, 1676 | { 1677 | "type": "STRING", 1678 | "value": "-" 1679 | } 1680 | ] 1681 | }, 1682 | { 1683 | "type": "BLANK" 1684 | } 1685 | ] 1686 | }, 1687 | { 1688 | "type": "PATTERN", 1689 | "value": "\\d*" 1690 | }, 1691 | { 1692 | "type": "CHOICE", 1693 | "members": [ 1694 | { 1695 | "type": "SEQ", 1696 | "members": [ 1697 | { 1698 | "type": "STRING", 1699 | "value": "." 1700 | }, 1701 | { 1702 | "type": "PATTERN", 1703 | "value": "\\d+" 1704 | } 1705 | ] 1706 | }, 1707 | { 1708 | "type": "SEQ", 1709 | "members": [ 1710 | { 1711 | "type": "PATTERN", 1712 | "value": "[eE]" 1713 | }, 1714 | { 1715 | "type": "CHOICE", 1716 | "members": [ 1717 | { 1718 | "type": "STRING", 1719 | "value": "-" 1720 | }, 1721 | { 1722 | "type": "BLANK" 1723 | } 1724 | ] 1725 | }, 1726 | { 1727 | "type": "PATTERN", 1728 | "value": "\\d+" 1729 | } 1730 | ] 1731 | }, 1732 | { 1733 | "type": "SEQ", 1734 | "members": [ 1735 | { 1736 | "type": "STRING", 1737 | "value": "." 1738 | }, 1739 | { 1740 | "type": "PATTERN", 1741 | "value": "\\d+" 1742 | }, 1743 | { 1744 | "type": "PATTERN", 1745 | "value": "[eE]" 1746 | }, 1747 | { 1748 | "type": "CHOICE", 1749 | "members": [ 1750 | { 1751 | "type": "STRING", 1752 | "value": "-" 1753 | }, 1754 | { 1755 | "type": "BLANK" 1756 | } 1757 | ] 1758 | }, 1759 | { 1760 | "type": "PATTERN", 1761 | "value": "\\d+" 1762 | } 1763 | ] 1764 | } 1765 | ] 1766 | } 1767 | ] 1768 | } 1769 | }, 1770 | { 1771 | "type": "CHOICE", 1772 | "members": [ 1773 | { 1774 | "type": "SYMBOL", 1775 | "name": "unit" 1776 | }, 1777 | { 1778 | "type": "BLANK" 1779 | } 1780 | ] 1781 | } 1782 | ] 1783 | }, 1784 | "unit": { 1785 | "type": "IMMEDIATE_TOKEN", 1786 | "content": { 1787 | "type": "PATTERN", 1788 | "value": "[a-zA-Z%]+" 1789 | } 1790 | }, 1791 | "grid_value": { 1792 | "type": "SEQ", 1793 | "members": [ 1794 | { 1795 | "type": "STRING", 1796 | "value": "[" 1797 | }, 1798 | { 1799 | "type": "SEQ", 1800 | "members": [ 1801 | { 1802 | "type": "SYMBOL", 1803 | "name": "_value" 1804 | }, 1805 | { 1806 | "type": "REPEAT", 1807 | "content": { 1808 | "type": "SEQ", 1809 | "members": [ 1810 | { 1811 | "type": "STRING", 1812 | "value": "," 1813 | }, 1814 | { 1815 | "type": "SYMBOL", 1816 | "name": "_value" 1817 | } 1818 | ] 1819 | } 1820 | } 1821 | ] 1822 | }, 1823 | { 1824 | "type": "STRING", 1825 | "value": "]" 1826 | } 1827 | ] 1828 | }, 1829 | "call_expression": { 1830 | "type": "SEQ", 1831 | "members": [ 1832 | { 1833 | "type": "ALIAS", 1834 | "content": { 1835 | "type": "SYMBOL", 1836 | "name": "identifier" 1837 | }, 1838 | "named": true, 1839 | "value": "function_name" 1840 | }, 1841 | { 1842 | "type": "SYMBOL", 1843 | "name": "arguments" 1844 | } 1845 | ] 1846 | }, 1847 | "binary_expression": { 1848 | "type": "PREC_LEFT", 1849 | "value": 0, 1850 | "content": { 1851 | "type": "SEQ", 1852 | "members": [ 1853 | { 1854 | "type": "SYMBOL", 1855 | "name": "_value" 1856 | }, 1857 | { 1858 | "type": "CHOICE", 1859 | "members": [ 1860 | { 1861 | "type": "STRING", 1862 | "value": "+" 1863 | }, 1864 | { 1865 | "type": "STRING", 1866 | "value": "-" 1867 | }, 1868 | { 1869 | "type": "STRING", 1870 | "value": "*" 1871 | }, 1872 | { 1873 | "type": "STRING", 1874 | "value": "/" 1875 | } 1876 | ] 1877 | }, 1878 | { 1879 | "type": "SYMBOL", 1880 | "name": "_value" 1881 | } 1882 | ] 1883 | } 1884 | }, 1885 | "arguments": { 1886 | "type": "SEQ", 1887 | "members": [ 1888 | { 1889 | "type": "IMMEDIATE_TOKEN", 1890 | "content": { 1891 | "type": "STRING", 1892 | "value": "(" 1893 | } 1894 | }, 1895 | { 1896 | "type": "CHOICE", 1897 | "members": [ 1898 | { 1899 | "type": "SEQ", 1900 | "members": [ 1901 | { 1902 | "type": "REPEAT1", 1903 | "content": { 1904 | "type": "SYMBOL", 1905 | "name": "_value" 1906 | } 1907 | }, 1908 | { 1909 | "type": "REPEAT", 1910 | "content": { 1911 | "type": "SEQ", 1912 | "members": [ 1913 | { 1914 | "type": "CHOICE", 1915 | "members": [ 1916 | { 1917 | "type": "STRING", 1918 | "value": "," 1919 | }, 1920 | { 1921 | "type": "STRING", 1922 | "value": ";" 1923 | } 1924 | ] 1925 | }, 1926 | { 1927 | "type": "REPEAT1", 1928 | "content": { 1929 | "type": "SYMBOL", 1930 | "name": "_value" 1931 | } 1932 | } 1933 | ] 1934 | } 1935 | } 1936 | ] 1937 | }, 1938 | { 1939 | "type": "BLANK" 1940 | } 1941 | ] 1942 | }, 1943 | { 1944 | "type": "STRING", 1945 | "value": ")" 1946 | } 1947 | ] 1948 | }, 1949 | "identifier": { 1950 | "type": "PATTERN", 1951 | "value": "(--|-?[a-zA-Z_])[a-zA-Z0-9-_]*" 1952 | }, 1953 | "at_keyword": { 1954 | "type": "PATTERN", 1955 | "value": "@[a-zA-Z-_]+" 1956 | }, 1957 | "js_comment": { 1958 | "type": "TOKEN", 1959 | "content": { 1960 | "type": "PREC", 1961 | "value": -1, 1962 | "content": { 1963 | "type": "SEQ", 1964 | "members": [ 1965 | { 1966 | "type": "STRING", 1967 | "value": "//" 1968 | }, 1969 | { 1970 | "type": "PATTERN", 1971 | "value": ".*" 1972 | } 1973 | ] 1974 | } 1975 | } 1976 | }, 1977 | "comment": { 1978 | "type": "TOKEN", 1979 | "content": { 1980 | "type": "SEQ", 1981 | "members": [ 1982 | { 1983 | "type": "STRING", 1984 | "value": "/*" 1985 | }, 1986 | { 1987 | "type": "PATTERN", 1988 | "value": "[^*]*\\*+([^/*][^*]*\\*+)*" 1989 | }, 1990 | { 1991 | "type": "STRING", 1992 | "value": "/" 1993 | } 1994 | ] 1995 | } 1996 | }, 1997 | "plain_value": { 1998 | "type": "TOKEN", 1999 | "content": { 2000 | "type": "SEQ", 2001 | "members": [ 2002 | { 2003 | "type": "REPEAT", 2004 | "content": { 2005 | "type": "CHOICE", 2006 | "members": [ 2007 | { 2008 | "type": "PATTERN", 2009 | "value": "[-_]" 2010 | }, 2011 | { 2012 | "type": "PATTERN", 2013 | "value": "\\/[^\\*\\s,;!{}()\\[\\]]" 2014 | } 2015 | ] 2016 | } 2017 | }, 2018 | { 2019 | "type": "PATTERN", 2020 | "value": "[a-zA-Z]" 2021 | }, 2022 | { 2023 | "type": "REPEAT", 2024 | "content": { 2025 | "type": "CHOICE", 2026 | "members": [ 2027 | { 2028 | "type": "PATTERN", 2029 | "value": "[^/\\s,;!{}()\\[\\]]" 2030 | }, 2031 | { 2032 | "type": "PATTERN", 2033 | "value": "\\/[^\\*\\s,;!{}()\\[\\]]" 2034 | } 2035 | ] 2036 | } 2037 | } 2038 | ] 2039 | } 2040 | }, 2041 | "_js_identifier": { 2042 | "type": "PATTERN", 2043 | "value": "[$_a-zA-Z0-9]+" 2044 | }, 2045 | "_js_string": { 2046 | "type": "TOKEN", 2047 | "content": { 2048 | "type": "CHOICE", 2049 | "members": [ 2050 | { 2051 | "type": "SEQ", 2052 | "members": [ 2053 | { 2054 | "type": "STRING", 2055 | "value": "'" 2056 | }, 2057 | { 2058 | "type": "PATTERN", 2059 | "value": "([^'\\n]|\\\\(.|\\n))*" 2060 | }, 2061 | { 2062 | "type": "STRING", 2063 | "value": "'" 2064 | } 2065 | ] 2066 | }, 2067 | { 2068 | "type": "SEQ", 2069 | "members": [ 2070 | { 2071 | "type": "STRING", 2072 | "value": "\"" 2073 | }, 2074 | { 2075 | "type": "PATTERN", 2076 | "value": "([^\"\\n]|\\\\(.|\\n))*" 2077 | }, 2078 | { 2079 | "type": "STRING", 2080 | "value": "\"" 2081 | } 2082 | ] 2083 | }, 2084 | { 2085 | "type": "SEQ", 2086 | "members": [ 2087 | { 2088 | "type": "STRING", 2089 | "value": "`" 2090 | }, 2091 | { 2092 | "type": "PATTERN", 2093 | "value": "([^`\\n]|\\\\(.|\\n))*" 2094 | }, 2095 | { 2096 | "type": "STRING", 2097 | "value": "`" 2098 | } 2099 | ] 2100 | } 2101 | ] 2102 | } 2103 | }, 2104 | "_js_expr": { 2105 | "type": "CHOICE", 2106 | "members": [ 2107 | { 2108 | "type": "SYMBOL", 2109 | "name": "_js_string" 2110 | }, 2111 | { 2112 | "type": "PREC_RIGHT", 2113 | "value": 1, 2114 | "content": { 2115 | "type": "SEQ", 2116 | "members": [ 2117 | { 2118 | "type": "SYMBOL", 2119 | "name": "_js_expr" 2120 | }, 2121 | { 2122 | "type": "PATTERN", 2123 | "value": "\\+\\-\\*\\/%" 2124 | }, 2125 | { 2126 | "type": "SYMBOL", 2127 | "name": "_js_expr" 2128 | } 2129 | ] 2130 | } 2131 | }, 2132 | { 2133 | "type": "PREC_RIGHT", 2134 | "value": 1, 2135 | "content": { 2136 | "type": "SEQ", 2137 | "members": [ 2138 | { 2139 | "type": "SYMBOL", 2140 | "name": "_js_expr" 2141 | }, 2142 | { 2143 | "type": "STRING", 2144 | "value": "??" 2145 | }, 2146 | { 2147 | "type": "SYMBOL", 2148 | "name": "_js_expr" 2149 | } 2150 | ] 2151 | } 2152 | }, 2153 | { 2154 | "type": "PREC_RIGHT", 2155 | "value": 0, 2156 | "content": { 2157 | "type": "SEQ", 2158 | "members": [ 2159 | { 2160 | "type": "SYMBOL", 2161 | "name": "_js_expr" 2162 | }, 2163 | { 2164 | "type": "STRING", 2165 | "value": "?" 2166 | }, 2167 | { 2168 | "type": "SYMBOL", 2169 | "name": "_js_expr" 2170 | }, 2171 | { 2172 | "type": "STRING", 2173 | "value": ":" 2174 | }, 2175 | { 2176 | "type": "SYMBOL", 2177 | "name": "_js_expr" 2178 | } 2179 | ] 2180 | } 2181 | }, 2182 | { 2183 | "type": "SEQ", 2184 | "members": [ 2185 | { 2186 | "type": "SYMBOL", 2187 | "name": "_js_identifier" 2188 | }, 2189 | { 2190 | "type": "CHOICE", 2191 | "members": [ 2192 | { 2193 | "type": "CHOICE", 2194 | "members": [ 2195 | { 2196 | "type": "SEQ", 2197 | "members": [ 2198 | { 2199 | "type": "PATTERN", 2200 | "value": "\\??\\." 2201 | }, 2202 | { 2203 | "type": "SYMBOL", 2204 | "name": "_js_identifier" 2205 | } 2206 | ] 2207 | }, 2208 | { 2209 | "type": "SEQ", 2210 | "members": [ 2211 | { 2212 | "type": "CHOICE", 2213 | "members": [ 2214 | { 2215 | "type": "PATTERN", 2216 | "value": "\\??\\." 2217 | }, 2218 | { 2219 | "type": "BLANK" 2220 | } 2221 | ] 2222 | }, 2223 | { 2224 | "type": "STRING", 2225 | "value": "(" 2226 | }, 2227 | { 2228 | "type": "CHOICE", 2229 | "members": [ 2230 | { 2231 | "type": "SYMBOL", 2232 | "name": "_js_args" 2233 | }, 2234 | { 2235 | "type": "BLANK" 2236 | } 2237 | ] 2238 | }, 2239 | { 2240 | "type": "STRING", 2241 | "value": ")" 2242 | } 2243 | ] 2244 | }, 2245 | { 2246 | "type": "SEQ", 2247 | "members": [ 2248 | { 2249 | "type": "CHOICE", 2250 | "members": [ 2251 | { 2252 | "type": "PATTERN", 2253 | "value": "\\??\\." 2254 | }, 2255 | { 2256 | "type": "BLANK" 2257 | } 2258 | ] 2259 | }, 2260 | { 2261 | "type": "STRING", 2262 | "value": "[" 2263 | }, 2264 | { 2265 | "type": "SYMBOL", 2266 | "name": "_js_expr" 2267 | }, 2268 | { 2269 | "type": "STRING", 2270 | "value": "]" 2271 | } 2272 | ] 2273 | } 2274 | ] 2275 | }, 2276 | { 2277 | "type": "BLANK" 2278 | } 2279 | ] 2280 | } 2281 | ] 2282 | } 2283 | ] 2284 | }, 2285 | "_js_param": { 2286 | "type": "CHOICE", 2287 | "members": [ 2288 | { 2289 | "type": "SYMBOL", 2290 | "name": "_js_identifier" 2291 | }, 2292 | { 2293 | "type": "SEQ", 2294 | "members": [ 2295 | { 2296 | "type": "STRING", 2297 | "value": "{" 2298 | }, 2299 | { 2300 | "type": "SYMBOL", 2301 | "name": "_js_params" 2302 | }, 2303 | { 2304 | "type": "STRING", 2305 | "value": "}" 2306 | } 2307 | ] 2308 | } 2309 | ] 2310 | }, 2311 | "_js_params": { 2312 | "type": "SEQ", 2313 | "members": [ 2314 | { 2315 | "type": "SYMBOL", 2316 | "name": "_js_param" 2317 | }, 2318 | { 2319 | "type": "REPEAT", 2320 | "content": { 2321 | "type": "SEQ", 2322 | "members": [ 2323 | { 2324 | "type": "STRING", 2325 | "value": "," 2326 | }, 2327 | { 2328 | "type": "SYMBOL", 2329 | "name": "_js_param" 2330 | } 2331 | ] 2332 | } 2333 | } 2334 | ] 2335 | }, 2336 | "_js_args": { 2337 | "type": "SEQ", 2338 | "members": [ 2339 | { 2340 | "type": "SYMBOL", 2341 | "name": "_js_expr" 2342 | }, 2343 | { 2344 | "type": "REPEAT", 2345 | "content": { 2346 | "type": "SEQ", 2347 | "members": [ 2348 | { 2349 | "type": "STRING", 2350 | "value": "," 2351 | }, 2352 | { 2353 | "type": "SYMBOL", 2354 | "name": "_js_expr" 2355 | } 2356 | ] 2357 | } 2358 | } 2359 | ] 2360 | }, 2361 | "_js_fat_arrow_function": { 2362 | "type": "SEQ", 2363 | "members": [ 2364 | { 2365 | "type": "CHOICE", 2366 | "members": [ 2367 | { 2368 | "type": "SYMBOL", 2369 | "name": "_js_identifier" 2370 | }, 2371 | { 2372 | "type": "SEQ", 2373 | "members": [ 2374 | { 2375 | "type": "STRING", 2376 | "value": "(" 2377 | }, 2378 | { 2379 | "type": "CHOICE", 2380 | "members": [ 2381 | { 2382 | "type": "SYMBOL", 2383 | "name": "_js_params" 2384 | }, 2385 | { 2386 | "type": "BLANK" 2387 | } 2388 | ] 2389 | }, 2390 | { 2391 | "type": "STRING", 2392 | "value": ")" 2393 | } 2394 | ] 2395 | } 2396 | ] 2397 | }, 2398 | { 2399 | "type": "STRING", 2400 | "value": "=>" 2401 | }, 2402 | { 2403 | "type": "SYMBOL", 2404 | "name": "_js_expr" 2405 | } 2406 | ] 2407 | }, 2408 | "js_interpolation": { 2409 | "type": "SEQ", 2410 | "members": [ 2411 | { 2412 | "type": "STRING", 2413 | "value": "${" 2414 | }, 2415 | { 2416 | "type": "CHOICE", 2417 | "members": [ 2418 | { 2419 | "type": "SYMBOL", 2420 | "name": "_js_expr" 2421 | }, 2422 | { 2423 | "type": "SYMBOL", 2424 | "name": "_js_fat_arrow_function" 2425 | } 2426 | ] 2427 | }, 2428 | { 2429 | "type": "STRING", 2430 | "value": "}" 2431 | } 2432 | ] 2433 | } 2434 | }, 2435 | "extras": [ 2436 | { 2437 | "type": "PATTERN", 2438 | "value": "\\s" 2439 | }, 2440 | { 2441 | "type": "SYMBOL", 2442 | "name": "comment" 2443 | }, 2444 | { 2445 | "type": "SYMBOL", 2446 | "name": "js_comment" 2447 | } 2448 | ], 2449 | "conflicts": [], 2450 | "precedences": [], 2451 | "externals": [ 2452 | { 2453 | "type": "SYMBOL", 2454 | "name": "_descendant_operator" 2455 | }, 2456 | { 2457 | "type": "SYMBOL", 2458 | "name": "_pseudo_class_selector_colon" 2459 | }, 2460 | { 2461 | "type": "SYMBOL", 2462 | "name": "__error_recovery" 2463 | } 2464 | ], 2465 | "inline": [ 2466 | "_top_level_item", 2467 | "_block_item" 2468 | ], 2469 | "supertypes": [] 2470 | } 2471 | 2472 | --------------------------------------------------------------------------------