├── .gitignore ├── .dev-assets ├── syntax-issues │ ├── archive │ │ ├── aspect-ratio.css │ │ ├── light-dark-func.css │ │ ├── at-supports.css │ │ ├── at-page.css │ │ ├── clamp-arithmetic-operators.css │ │ ├── calc-in-at-media.css │ │ ├── calc-nesting.css │ │ └── at-container.css │ ├── grid-placement-slash.css │ ├── at-layer.css │ ├── at-media-propertie.css │ ├── at-import.css │ └── of-not.css ├── Sketch │ └── VSCode-CSS-Nesting-Extension-Logo.sketch ├── rule-lists.jsonc └── get-shared-names.js ├── .gitattributes ├── .vscodeignore ├── .prettierrc ├── images ├── css-nesting-syntax-highlighting-logo.png └── css-nesting-syntax-highlighting-logo-no-border.png ├── .vscode └── launch.json ├── demo ├── css-nesting-invalid.css ├── css-nesting-demo.css └── css-nesting-modules.css ├── LICENSE ├── package.json ├── CHANGELOG.md ├── README.md └── syntaxes └── css.tmLanguage.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.vsix -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/archive/aspect-ratio.css: -------------------------------------------------------------------------------- 1 | .class { 2 | aspect-ratio: 1; 3 | } 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/archive/light-dark-func.css: -------------------------------------------------------------------------------- 1 | .class { 2 | color: light-dark(white, black); 3 | } 4 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .dev-assets/** 2 | .vscode/** 3 | .vscode-test/** 4 | .gitignore 5 | vsc-extension-quickstart.md 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "overrides": [ 3 | { 4 | "files": "*.json", 5 | "options": { 6 | "useTabs": true 7 | } 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/archive/at-supports.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --supports-red: false; 3 | @supports (color: red) { 4 | --supports-red: true; 5 | } 6 | --x: 1; 7 | } 8 | -------------------------------------------------------------------------------- /images/css-nesting-syntax-highlighting-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobcassidy/vscode-css-nesting-syntax-highlighting/HEAD/images/css-nesting-syntax-highlighting-logo.png -------------------------------------------------------------------------------- /images/css-nesting-syntax-highlighting-logo-no-border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobcassidy/vscode-css-nesting-syntax-highlighting/HEAD/images/css-nesting-syntax-highlighting-logo-no-border.png -------------------------------------------------------------------------------- /.dev-assets/Sketch/VSCode-CSS-Nesting-Extension-Logo.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobcassidy/vscode-css-nesting-syntax-highlighting/HEAD/.dev-assets/Sketch/VSCode-CSS-Nesting-Extension-Logo.sketch -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/grid-placement-slash.css: -------------------------------------------------------------------------------- 1 | /** 2 | * GRID PLACEMENT SLASH 3 | */ 4 | 5 | /* Property value slash doesn't have its own syntax highlighting */ 6 | .example { 7 | grid-row: 1 / 3; 8 | grid-column: 1/-1; 9 | } 10 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/archive/at-page.css: -------------------------------------------------------------------------------- 1 | /** 2 | * AT PAGE 3 | */ 4 | 5 | @page { 6 | content: "Page " counter(pageNumber); 7 | } 8 | 9 | @page { 10 | /* margin box at top right showing page number */ 11 | @top-right { 12 | content: "Page " counter(pageNumber); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/at-layer.css: -------------------------------------------------------------------------------- 1 | /** 2 | * AT LAYER 3 | */ 4 | 5 | /* layer name has no syntax highlighting */ 6 | .foo { 7 | @layer base { 8 | block-size: 100%; 9 | @layer support { 10 | & .bar { 11 | min-block-size: 100%; 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/at-media-propertie.css: -------------------------------------------------------------------------------- 1 | /** 2 | * AT MEDIA PROPERTY 3 | */ 4 | 5 | /* Missing token for `prefers-reduced-motion: reduce` */ 6 | @media (prefers-reduced-motion: reduce) { 7 | } 8 | 9 | /* NOTE: see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries#descriptors for more media properties */ 10 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/at-import.css: -------------------------------------------------------------------------------- 1 | /** 2 | * AT IMPORT 3 | */ 4 | 5 | /* new syntax rules for @import have no syntax highlighting */ 6 | @import url("green.css") layer supports(selector(&)) (min-width: calc(10px)); 7 | 8 | /* layer as a function */ 9 | @import url("green.css") layer(bar) supports(selector(&)) 10 | (min-width: calc(10px)); 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/of-not.css: -------------------------------------------------------------------------------- 1 | /** 2 | * OF :NOT 3 | */ 4 | 5 | /* `of` and trailing grammar has no syntax highlighting */ 6 | .item > div:nth-child(1 of :not(.hidden)) { 7 | padding-left: var(--item_margin); 8 | } 9 | .item > div:nth-last-child(1 of :not(.hidden)) { 10 | padding-right: var(--item_margin); 11 | } 12 | 13 | /* Same as above, but using CSS Nesting formatting */ 14 | .item { 15 | & > div { 16 | &:nth-child(1 of :not(.hidden)) { 17 | padding-left: var(--item_margin); 18 | } 19 | &:nth-last-child(1 of :not(.hidden)) { 20 | padding-right: var(--item_margin); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/archive/clamp-arithmetic-operators.css: -------------------------------------------------------------------------------- 1 | /** 2 | * FUNCTION ARITHMETIC OPERATORS 3 | */ 4 | 5 | .example { 6 | margin-block-start: clamp(15px, 0.805rem + 0.64vw, 18px); 7 | margin-block-end: clamp(15px, 0.805rem - 0.64vw, 18px); 8 | } 9 | 10 | .other-examples { 11 | width: clamp(100px, calc(30% / 2rem + 10px), 900px); 12 | width: min(1000px, calc(70% + 100px)); 13 | font-size: clamp(1.1rem, 0.7153rem + 1.6368vw, 1.5rem); 14 | width: max(300px, 50% + 20px); 15 | width: min(300px, 50% + 20px); 16 | height: calc(var(--base-height) + 10%); 17 | font-size: clamp(15px, 0.805rem + 0.64vw, 18px); 18 | width: calc(100% - 20px); 19 | } 20 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/archive/calc-in-at-media.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CALC FUNCTION IN @MEDIA 3 | */ 4 | 5 | :root { 6 | --size: 500px; 7 | } 8 | 9 | .example { 10 | max-width: calc(var(--size) * 1rem); 11 | } 12 | 13 | @media screen and (min-width: calc( var(--size) * 1rem)) { 14 | .example { 15 | max-width: calc(var(--size) * 1rem); 16 | } 17 | } 18 | 19 | /* With CSS nesting */ 20 | @media only screen and (max-width: calc( var(--size) * 1rem)) { 21 | .example { 22 | span { 23 | max-width: calc(var(--size) * 1rem); 24 | } 25 | } 26 | } 27 | 28 | .example { 29 | @media only screen and (max-width: calc( var(--size) * 1rem)) { 30 | span { 31 | max-width: calc(var(--size) * 1rem); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /demo/css-nesting-invalid.css: -------------------------------------------------------------------------------- 1 | /** 2 | * INVALID CSS NESTING 3 | */ 4 | 5 | /** 6 | * Concatenation (is not possible) 7 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting#concatenation_is_not_possible 8 | */ 9 | 10 | .component { 11 | &__child-element { 12 | margin: 0; 13 | } 14 | } 15 | /* In Sass this becomes the CSS below, but CSS nesting doesn't allow this */ 16 | .component__child-element { 17 | margin: 0; 18 | } 19 | 20 | /** 21 | * Invalid nested style rules 22 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting#invalid_nested_style_rules 23 | */ 24 | 25 | .parent { 26 | /* .parent styles these work fine */ 27 | & %invalid { 28 | /* %invalid styles all of which are ignored */ 29 | margin: 0; 30 | } 31 | & .valid { 32 | /* .parent .valid styles these work fine */ 33 | margin: 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/archive/calc-nesting.css: -------------------------------------------------------------------------------- 1 | /** 2 | * NESTED CALC FUNCTIONS 3 | */ 4 | 5 | .example { 6 | margin-top: calc(600 / 16 * 1rem); 7 | margin-bottom: calc( (768 / 16) * 1rem); 8 | margin-right: calc( (768 / 16 * (768 / 16) ) * 1rem); 9 | margin-left: calc( (768 / 16 * (768 / 16 + (768 / 16) ) ) * 1rem); 10 | padding-top: calc( (768 / 16 * (768 / 16 + (768 / 16 - (768 / 16) ) ) ) * 1rem); 11 | } 12 | 13 | /* Without CSS nesting */ 14 | @media screen and (max-width: calc( (1280 / 16) * 1rem)) { 15 | .example { 16 | max-width: calc((768 / 16) * 1rem); 17 | } 18 | } 19 | 20 | /* With CSS nesting */ 21 | @media only screen and (max-width: calc( (768 / 16) * 1rem )) { 22 | .example { 23 | max-width: calc((768 / 16) * 1rem); 24 | span { 25 | max-width: calc((600 / 16) * 1rem); 26 | } 27 | } 28 | } 29 | 30 | .example { 31 | @media only screen and (max-width: calc( var(--size) * 1rem)) { 32 | max-width: calc((768 / 16) * 1rem); 33 | span { 34 | max-width: calc((600 / 16) * 1rem); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 Jacob Cassidy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-nesting-syntax-highlighting", 3 | "displayName": "CSS Nesting Syntax Highlighting", 4 | "description": "Updates VSCode's CSS TextMate rules to add CSS Nesting", 5 | "version": "0.4.0", 6 | "icon": "images/css-nesting-syntax-highlighting-logo.png", 7 | "publisher": "jacobcassidy", 8 | "bugs": { 9 | "url": "https://github.com/jacobcassidy/vscode-css-nesting-syntax-highlighting/issues" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/jacobcassidy/vscode-css-nesting-syntax-highlighting" 14 | }, 15 | "galleryBanner": { 16 | "color": "#292929", 17 | "theme": "dark" 18 | }, 19 | "keywords": [ 20 | "CSS Nesting", 21 | "Nested CSS", 22 | "Nesting", 23 | "Nested", 24 | "Syntax", 25 | "Highlighting", 26 | "Colorizer" 27 | ], 28 | "engines": { 29 | "vscode": "^1.84.0" 30 | }, 31 | "categories": [ 32 | "Programming Languages" 33 | ], 34 | "contributes": { 35 | "grammars": [ 36 | { 37 | "language": "css", 38 | "scopeName": "source.css", 39 | "path": "./syntaxes/css.tmLanguage.json" 40 | } 41 | ] 42 | }, 43 | "__metadata": { 44 | "id": "dc07370c-e087-43f1-91fe-4f44363dc5d7", 45 | "publisherId": "aee9e75c-ea26-4af1-b5e6-815e33288c4b", 46 | "publisherDisplayName": "Jacob Cassidy", 47 | "targetPlatform": "undefined", 48 | "updated": false, 49 | "isPreReleaseVersion": false, 50 | "hasPreReleaseVersion": false, 51 | "installedTimestamp": 1736203061589, 52 | "pinned": false, 53 | "size": 146700, 54 | "isApplicationScoped": false, 55 | "preRelease": false, 56 | "source": "gallery" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.dev-assets/rule-lists.jsonc: -------------------------------------------------------------------------------- 1 | // SCSS: 2 | // ------ 3 | // rules 4 | // > selectors 5 | // >> source.css#tag-names 6 | // >> selector_class 7 | // >> selector_id 8 | // >> selector_pseudo_class 9 | // >> tag_parent_reference >>> & 10 | // >> source.css#pseudo-elements 11 | // >> selector_attribute 12 | // property_list 13 | // > {}; 14 | // > ^...rules 15 | // > properties 16 | // >> source.css#property-names 17 | // >> : -> ; >> property_values 18 | // >>> source.css#numeric-values 19 | // >>> source.css#property-keywords 20 | // >>> source.css#property-names 21 | // >>> () >>>> property_values 22 | // > self 23 | // ; 24 | 25 | // CSS: 26 | // ------ 27 | // #selector 28 | // > #selector-innards 29 | // >> #tag-names 30 | // >> entity.other.attribute-name.class.css 31 | // >> entity.other.attribute-name.id.css 32 | // >> #pseudo-classes 33 | // + >> #nesting-selector 34 | // >> #pseudo-elements 35 | // >> #functional-pseudo-classes 36 | // #rule-list 37 | // > {} 38 | // + ^...#selector-innards 39 | // > #rule-list-innards 40 | // >> word >> #property-names 41 | // >> : -> ; >> #property-values 42 | // >> ; 43 | // + > self 44 | 45 | 46 | 47 | // { 48 | // "include": "#at-rules" 49 | // }, 50 | // { 51 | // "include": "#property-names" 52 | // }, 53 | // { 54 | // "include": "#tag-names" 55 | // }, 56 | // { 57 | // "include": "#pseudo-classes" 58 | // }, 59 | // { 60 | // "include": "#pseudo-elements" 61 | // }, 62 | // { 63 | // "include": "#functional-pseudo-classes" 64 | // }, 65 | 66 | 67 | 68 | // { 69 | // "include": "#property-names" 70 | // }, 71 | // { 72 | // "include": "#tag-names" 73 | // }, 74 | // { 75 | // "include": "#pseudo-classes" 76 | // }, 77 | // { 78 | // "include": "#nesting-selector" 79 | // }, 80 | // { 81 | // "include": "#pseudo-elements" 82 | // }, 83 | // { 84 | // "include": "#functional-pseudo-classes" 85 | // }, 86 | // { 87 | // "include": "#rule-list-innards" 88 | // }, 89 | // { 90 | // "include": "$self" 91 | // } 92 | 93 | 94 | 95 | 96 | // { 97 | // "include": "#selector-innards" 98 | // }, 99 | // { 100 | // "include": "#rule-list-innards" 101 | // }, 102 | // { 103 | // "include": "$self" 104 | // } 105 | -------------------------------------------------------------------------------- /.dev-assets/syntax-issues/archive/at-container.css: -------------------------------------------------------------------------------- 1 | /** 2 | * AT CONTAINER 3 | */ 4 | 5 | /* AND */ 6 | @container (width > 400px) and (height > 400px) { 7 | } 8 | @container (min-width: 600px) and (orientation: landscape) { 9 | } 10 | 11 | /* NOT */ 12 | @container not (width < 400px) { 13 | } 14 | @container not (width < 400px) not (width > 800px) { 15 | } 16 | @container sidebar not (orientation: landscape) and (min-width: 600px) { 17 | } 18 | @container sidebar not (orientation: landscape) and (min-width: 600px) or (min-width: 600px) { 19 | } 20 | 21 | /* OR */ 22 | @container (width > 400px) or (height > 400px) {'' 23 | } 24 | @container (display: grid) or (display: flex) { 25 | } 26 | 27 | /* CONTAINER-NAME */ 28 | @container name (width > 400px) and (height > 400px) { 29 | } 30 | @container name1 name2 name3 not (width > 400px) not (height > 400px) { 31 | } 32 | 33 | @container default (width > 400px) { 34 | } 35 | @container none default (width > 400px) { 36 | } 37 | 38 | /* CONTAINER-QUERY */ 39 | @container (min-aspect-ratio: 3 / 2) { 40 | .video-player { 41 | border: 5px solid #fff; 42 | } 43 | } 44 | 45 | @container (min-width: calc( var(--width) * 1rem)) { 46 | .card { 47 | margin: 0; 48 | } 49 | } 50 | 51 | /* STYLE-QUERY */ 52 | @container style( --accent-color : currentColor ) { 53 | } 54 | 55 | @container style(small --cards: /*comment*/ small 333px) { 56 | } 57 | @container card (inline-size > 30em) and style(--responsive: true) { 58 | } 59 | @container style( --width : calc( var(--hello) ) ) { 60 | } 61 | 62 | @container style(--themeBackground), not style(--themeColor: blue), style(--themeColor: blue) and style(--themeColor: purple), style(--themeColor: blue) or style(--themeColor: purple) { 63 | } 64 | @container card (inline-size > 30em) and style(--responsive: true) { 65 | } 66 | @container style(--cards: 333px) { 67 | article { 68 | border: thin solid silver; 69 | border-radius: 0.5em; 70 | padding: 1em; 71 | } 72 | } 73 | 74 | /* NESTED @CONTAINER */ 75 | @container summary (width > 400px) { 76 | @container (min-width: 800px) { 77 | .card { 78 | margin: 50px; 79 | } 80 | @container (min-width: calc( var(--width) * 1rem)) { 81 | .card { 82 | margin: 0; 83 | } 84 | } 85 | } 86 | } 87 | @container card (inline-size > 30em) { 88 | @container style(--responsive: true) { 89 | /* styles */ 90 | } 91 | } 92 | 93 | /* EVERYTHING */ 94 | @container /*comment*/ tall /*comment*/ short not invalidName (width > 400px) and invalidName not (min-height: 400px /*comment*/ invalidName) /*comment*/ or style(--accent-color: currentColor) { 95 | .card { 96 | margin: 0; 97 | .example { 98 | margin: 0; 99 | } 100 | } 101 | } 102 | 103 | @container name1 name2 not (max-width: calc( (768 / 16) * 1rem)) invalidName { 104 | invalidName .wp-block-buttons { 105 | margin: calc(var(--wp--custom--element-spacing) * 3) auto; 106 | .wp-block-button, 107 | .wp-element-button { 108 | width: 100%; 109 | } 110 | } 111 | } 112 | 113 | @container (10em <= width <= 20em) { 114 | /* styles */ 115 | } 116 | 117 | @container (inline-size >= 0px) { 118 | /* only applies when an inline-size container is available */ 119 | h2 { 120 | font-size: calc(1.2em + 1cqi); 121 | } 122 | } 123 | 124 | @container (width > 40em) { 125 | h2 { 126 | font-size: 1.5em; 127 | } 128 | } 129 | 130 | @container my-page-layout (block-size > 12em) { 131 | .card { 132 | margin-block: 2em; 133 | } 134 | } 135 | 136 | @container (inline-size >= 0px) { 137 | /* only applies when an inline-size container is available */ 138 | h2 { 139 | font-size: calc(1.2em + 1cqi); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [0.4.0] - 2025-01-31 9 | 10 | ### Added 11 | 12 | - Added sheild.io badges to top of `README.md`. 13 | 14 | ## [0.3.0] - 2025-01-07 15 | 16 | ### Added 17 | 18 | - Added `aspect-ratio` property to list of property-names, matching the latest commit to VSCode. 19 | - Added `light-dark` to list of color functions for proper syntax highlighting. 20 | 21 | ## [0.2.0] - 2025-01-06 22 | 23 | ### Added 24 | 25 | - Added nesting syntax highlighting for body of `@support` rule. 26 | 27 | ### Changed 28 | 29 | - Updated CHANGELOG.md to follow formatting set by [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). 30 | 31 | ## [0.1.1] - 2024-08-25 32 | 33 | ### Changed 34 | 35 | - Updated `README.md` with Table of Contents and better organization. 36 | 37 | ## [0.1.0] - 2024-03-15 38 | 39 | ### Changed 40 | 41 | - Changed `package.json` vscode engine to v1.84.0 and above to allow users on older versions to use the extension. 42 | 43 | ## [0.0.9] - 2024-02-24 44 | 45 | ### Added 46 | 47 | - Added tokens for `@container` syntax highlighting. 48 | 49 | ```css 50 | /* Nested @container example */ 51 | @container summary (width > 400px) { 52 | @container (min-width: 800px) { 53 | .card { 54 | margin: 50px; 55 | } 56 | @container (min-width: calc( var(--width) * 1rem)) { 57 | .card { 58 | margin: 0; 59 | } 60 | } 61 | } 62 | } 63 | ``` 64 | 65 | ## [0.0.8] - 2024-02-22 66 | 67 | ### Added 68 | 69 | - Added `#arithmetic-operators` for functions (clamp, min, max) operator syntax highlighting. 70 | 71 | ```css 72 | .arithmetic-operators-example { 73 | font-size: clamp(1.1rem, 0.7153rem + 1.6368vw, 1.5rem); 74 | width: max(300px, 50% + 20px); 75 | } 76 | ``` 77 | 78 | ## [0.0.7] - 2024-02-22 79 | 80 | ### Changed 81 | 82 | - Revert package.json language keyword to lowercase as extension doesn't work if it is uppercase. 83 | 84 | ## [0.0.6] - 2024-02-22 85 | 86 | ### Added 87 | 88 | - Added syntax highlighting for functions in media-query header. 89 | - Added syntax highlighting for nested `calc()` functions. 90 | 91 | ```css 92 | /* Example of a nested calc function */ 93 | .example { 94 | max-width: calc( (768 / 16) * 1rem) ) { 95 | } 96 | /* Example of functions in media-query header */ 97 | @media only screen and (max-width: calc( var(--size) * 1rem)) {} 98 | ``` 99 | 100 | ## [0.0.5] - 2024-02-21 101 | 102 | ### Added 103 | 104 | - Added note to reload VSCode after installing this extension. 105 | 106 | ## [0.0.4] - 2024-02-19 107 | 108 | ### Changed 109 | 110 | - Added border to logo image for contrast on dark backgrounds. 111 | 112 | ## [0.0.3] - 2024-02-19 113 | 114 | ### Added 115 | 116 | - Added `.dev-assets` directory with CSS files containing syntax errors, a rule lists, and a getSharedNames() function for finding shared names between `#tag-names` and `#property-names`. 117 | - Added `&` to the allowed list of characters that can be appended to a tag, class, or ID, so it can be used as a CSS nesting compound selector. 118 | - Added `#nesting-selector` rule with `&`. 119 | - Added `#nesting-rules` and `#nesting-at-rules` to include CSS nesting syntax highlighting. 120 | - Added `"include": "$self"` to `rule-list` for nested `{}`. 121 | - Added extension's logo image. 122 | - Added `.prettierrc` file for formatting json with tabs. 123 | 124 | ### Changed 125 | 126 | - Updated demo CSS. 127 | - Updated other CSS for review and testing. 128 | 129 | ### Removed 130 | 131 | - Removed `&` from invalid punctuation so it can be used as a CSS nesting selector. 132 | - Removed `language-configuration.json` and package.json's language contribution block pointing to it. 133 | 134 | ## [0.0.2] - 2024-02-17 135 | 136 | ### Added 137 | 138 | - Added demo CSS files for testing and review. 139 | 140 | ## [0.0.1] - 2024-02-16 141 | 142 | ### Added 143 | 144 | - Added initial files to match VSCode core CSS syntax highlighting. 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS Nesting Syntax Highlighting 2 | 3 | [![vs marketplace](https://img.shields.io/vscode-marketplace/v/jacobcassidy.css-nesting-syntax-highlighting.svg?label=vs%20marketplace)](https://marketplace.visualstudio.com/items?itemName=jacobcassidy.css-nesting-syntax-highlighting) [![Visual Studio Marketplace Downloads](https://img.shields.io/visual-studio-marketplace/d/jacobcassidy.css-nesting-syntax-highlighting)](https://marketplace.visualstudio.com/items?itemName=jacobcassidy.css-nesting-syntax-highlighting) [![Visual Studio Marketplace Rating](https://img.shields.io/visual-studio-marketplace/r/jacobcassidy.css-nesting-syntax-highlighting)](https://marketplace.visualstudio.com/items?itemName=jacobcassidy.css-nesting-syntax-highlighting&ssr=false#review-details) [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/jacobcassidy/vscode-css-nesting-syntax-highlighting)](https://github.com/jacobcassidy/vscode-css-nesting-syntax-highlighting/commits/main/) 4 | 5 | | Table of Contents | 6 | | ------------------------------------------- | 7 | | [Overview](#overview) | 8 | | [CSS Nesting Example](#css-nesting-example) | 9 | | [Other Features](#other-features) | 10 | | [Installation](#installation) | 11 | | [Companion Theme](#companion-theme) | 12 | | [What's New](#whats-new) | 13 | | [Known Issues](#known-issues) | 14 | | [Reporting Issues](#issues) | 15 | 16 | ## Overview 17 | 18 | All modern browsers support CSS nesting ([Can I Use](https://caniuse.com/css-nesting)), but Visual Studio Code doesn't currently have CSS nesting syntax highlighting. This extension rectifies that by updating the CSS syntax highlighting to include nesting ([and more](#other-features)). 19 | 20 | To learn more about CSS Nesting, see [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting). 21 | 22 | The core CSS syntax file this extension updates can be found in the [official vscode repo](https://github.com/Microsoft/vscode/blob/main/extensions/css/syntaxes/css.tmLanguage.json). 23 | 24 | ## CSS Nesting Example 25 | 26 | ```css 27 | .example { 28 | text-decoration: none; 29 | &:hover { 30 | text-decoration: underline; 31 | } 32 | } 33 | 34 | /* The browser parses this as: */ 35 | .example { 36 | text-decoration: none; 37 | } 38 | .example:hover { 39 | text-decoration: underline; 40 | } 41 | ``` 42 | 43 | ## Other Features 44 | 45 | ### Includes syntax highlighting for `@container` 46 | 47 | ```css 48 | /* Nested @container example */ 49 | @container summary (width > 400px) { 50 | @container (min-width: 800px) { 51 | .card { 52 | margin: 50px; 53 | } 54 | @container (min-width: calc( var(--width) * 1rem)) { 55 | .card { 56 | margin: 0; 57 | } 58 | } 59 | } 60 | ``` 61 | 62 | ### Includes _function_ syntax highlighting for 'at-rules', such as in `@media` 63 | 64 | ```css 65 | /* calc() function example */ 66 | @media (max-width: calc( (768 / 16) * 1rem )) { 67 | .example { 68 | margin: 0; 69 | } 70 | } 71 | ``` 72 | 73 | ## Installation 74 | 75 | > Note: You may need to reload VSCode after installing this extension for it to take effect. 76 | 77 | Search for `CSS Nesting Syntax Highlighting` in the VSCode's Extensions Marketplace panel or click the install button on the [CSS Nesting Syntax Highlighting Marketplace page](https://marketplace.visualstudio.com/items?itemName=jacobcassidy.css-nesting-syntax-highlighting). 78 | 79 | You can also manually install the extension by cloning the [github repository](https://github.com/jacobcassidy/vscode-css-nesting-syntax-highlighting) into `~/.vscode/extensions` and restarting the VSCode editor. 80 | 81 | ## Companion Theme 82 | 83 | CSS Nesting Syntax Highlighting works great with the [Cassidy Dark Theme](https://marketplace.visualstudio.com/items?itemName=jacobcassidy.cassidy-dark). 84 | 85 | ## What's New? 86 | 87 | View the [Changelog](https://github.com/jacobcassidy/vscode-css-nesting-syntax-highlighting/blob/main/CHANGELOG.md). 88 | 89 | ## Known Issues 90 | 91 | - When nested, a few obscure `#tag-names` are overridden by the same `#property-names`. Those names are: 92 | - **HTML tags**: `content`, `font`, `image`, `marquee`, `mask`, `shadow`, `style`. 93 | - **SVG tags**: `color-profile`, `cursor`, `filter`, `line`, `text`. 94 | 95 | ## Issues? 96 | 97 | If you come across any issues, please feel free to [report them here](https://github.com/jacobcassidy/vscode-css-nesting-syntax-highlighting/issues). You can also [create a pull request](https://github.com/jacobcassidy/vscode-css-nesting-syntax-highlighting/pulls) to add any improvements. 98 | -------------------------------------------------------------------------------- /demo/css-nesting-demo.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS NESTING DEMO 3 | */ 4 | 5 | /** 6 | * Nesting without the `&` nesting selector 7 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/Nesting_selector 8 | */ 9 | 10 | .parent-rule { 11 | margin: 0; 12 | .child-rule { 13 | margin: 0; 14 | } 15 | } 16 | 17 | .parent-rule { 18 | text-decoration: none; 19 | :hover { 20 | text-decoration: underline; 21 | } 22 | } 23 | 24 | /** 25 | * Nesting with the `&` nesting selector 26 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/Nesting_selector 27 | */ 28 | 29 | .parent-rule { 30 | text-decoration: none; 31 | &:hover { 32 | text-decoration: underline; 33 | } 34 | } 35 | 36 | .example { 37 | font-family: system-ui; 38 | font-size: 1.2rem; 39 | & > a { 40 | color: tomato; 41 | &:hover, 42 | &:focus { 43 | color: ivory; 44 | background-color: tomato; 45 | } 46 | } 47 | } 48 | 49 | /** 50 | * Appending the `&` nesting selector 51 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/Nesting_selector#appending_the_nesting_selector 52 | */ 53 | 54 | .card { 55 | /* .card styles */ 56 | margin: 0; 57 | .featured & { 58 | /* .featured .card styles */ 59 | margin: 0; 60 | } 61 | } 62 | 63 | .card { 64 | /* .card styles */ 65 | margin: 0; 66 | .featured & & & { 67 | /* .featured .card .card .card styles */ 68 | margin: 0; 69 | } 70 | } 71 | 72 | .card { 73 | padding: 0.5rem; 74 | border: 1px solid black; 75 | border-radius: 0.5rem; 76 | & h2 { 77 | /* equivalent to `.card h2` */ 78 | color: slateblue; 79 | .featured & { 80 | /* equivalent to `:is(.card h2):is(.featured h2)` */ 81 | color: tomato; 82 | } 83 | } 84 | } 85 | 86 | /** 87 | * Appending the `&` nesting selector as a compound selector 88 | */ 89 | 90 | .example { 91 | section& { 92 | /* equivalent to `section.example` */ 93 | margin: 0; 94 | } 95 | .class& { 96 | /* equivalent to `.class.example` */ 97 | padding: 0; 98 | } 99 | #id& { 100 | /* equivalent to `#id.example` */ 101 | border: 1px solid black; 102 | } 103 | @media screen and (max-width: 1100px) { 104 | section& { 105 | margin: 0; 106 | } 107 | .class& { 108 | padding: 0; 109 | } 110 | #id& { 111 | margin: 0; 112 | } 113 | } 114 | } 115 | 116 | /** 117 | * Using `&` outside nested rule 118 | * If not used in nested style rule, the & nesting selector represents the scoping root. 119 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/Nesting_selector#using_outside_nested_rule 120 | */ 121 | 122 | & { 123 | color: blue; 124 | font-weight: bold; 125 | } 126 | 127 | &:hover { 128 | background-color: wheat; 129 | } 130 | 131 | /** 132 | * Nesting `@media` at-rule 133 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Nesting_at-rules#nesting_media_at-rule 134 | */ 135 | 136 | /* Typical way to write Nested CSS */ 137 | .foo { 138 | display: grid; 139 | @media (orientation: landscape) { 140 | grid-auto-flow: column; 141 | } 142 | } 143 | /* Expanded nested CSS as the browser parses it */ 144 | .foo { 145 | display: grid; 146 | @media (orientation: landscape) { 147 | & { 148 | grid-auto-flow: column; 149 | } 150 | } 151 | } 152 | 153 | /** 154 | * Multiple nested `@media` at-rule 155 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Nesting_at-rules#multiple_nested_media_at-rules 156 | */ 157 | 158 | .foo { 159 | display: grid; 160 | @media (orientation: landscape) { 161 | grid-auto-flow: column; 162 | @media (min-width: 1024px) { 163 | max-inline-size: 1024px; 164 | } 165 | } 166 | } 167 | 168 | /* Equivalent without nesting */ 169 | .foo { 170 | display: grid; 171 | } 172 | @media (orientation: landscape) { 173 | .foo { 174 | grid-auto-flow: column; 175 | } 176 | } 177 | @media (orientation: landscape) and (min-width: 1024px) { 178 | .foo { 179 | max-inline-size: 1024px; 180 | } 181 | } 182 | 183 | /** 184 | * Nesting Cascade Layers (`@layer`) 185 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Nesting_at-rules#nesting_cascade_layers_layer 186 | */ 187 | 188 | @layer base { 189 | @layer support; 190 | } 191 | 192 | .foo { 193 | @layer base { 194 | block-size: 100%; 195 | @layer support { 196 | & .bar { 197 | min-block-size: 100%; 198 | } 199 | } 200 | } 201 | } 202 | /* Equivalent without nesting */ 203 | @layer base { 204 | .foo { 205 | block-size: 100%; 206 | } 207 | } 208 | @layer base.support { 209 | .foo .bar { 210 | min-block-size: 100%; 211 | } 212 | } 213 | 214 | /** 215 | * Creating complex selectors with CSS nesting 216 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors/Selectors_and_combinators#creating_complex_selectors_with_css_nesting 217 | */ 218 | h2 { 219 | & + p { 220 | & ~ p { 221 | font-style: italic; 222 | } 223 | & + p { 224 | color: red; 225 | } 226 | } 227 | } 228 | .myClass { 229 | & + p { 230 | text-decoration: underline; 231 | } 232 | } 233 | #myId { 234 | & > .myClass { 235 | outline: 3px dashed red; 236 | } 237 | > p #anotherId { 238 | font-size: 1.1rem; 239 | } 240 | } 241 | 242 | /** 243 | * Nesting and compound selectors 244 | * See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting#compound_selectors 245 | */ 246 | 247 | .notice { 248 | color: black; 249 | padding: 1rem; 250 | .notice-heading:before { 251 | /* equivalent to `.notice .notice-heading:before` */ 252 | content: "ℹ︎ "; 253 | } 254 | &.warning { 255 | /* equivalent to `.notice.warning` */ 256 | background-color: #d81b60; 257 | border-color: #d81b60; 258 | color: white; 259 | .warning-heading:before { 260 | /* equivalent to `.notice.warning .warning-heading:before` */ 261 | content: "! "; 262 | } 263 | } 264 | &.success { 265 | /* equivalent to `.notice.success` */ 266 | background-color: #004d40; 267 | border-color: #004d40; 268 | color: white; 269 | .success-heading:before { 270 | /* equivalent to `.notice.success .success-heading:before` */ 271 | content: "✓ "; 272 | } 273 | } 274 | } 275 | 276 | .notice { 277 | color: black; 278 | padding: 1rem; 279 | .notice-heading:before { 280 | /* equivalent to `.notice .notice-heading:before` */ 281 | content: "ℹ︎ "; 282 | } 283 | .warning { 284 | /* equivalent to `.notice.warning` */ 285 | background-color: #d81b60; 286 | border-color: #d81b60; 287 | color: white; 288 | .warning-heading:before { 289 | /* equivalent to `.notice.warning .warning-heading:before` */ 290 | content: "! "; 291 | } 292 | } 293 | .success { 294 | /* equivalent to `.notice.success` */ 295 | background-color: #004d40; 296 | border-color: #004d40; 297 | color: white; 298 | .success-heading:before { 299 | /* equivalent to `.notice.success .success-heading:before` */ 300 | content: "✓ "; 301 | } 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /demo/css-nesting-modules.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS NESTING MODULES 3 | * For reviewing CSS nesting and non-nesting syntax For any issues. 4 | */ 5 | 6 | /** 7 | * At Rules 8 | */ 9 | 10 | @container (width > 400px) { 11 | h2 { 12 | font-size: 1.5em; 13 | } 14 | .card { 15 | width: 50%; 16 | background-color: gray; 17 | font-size: 1em; 18 | } 19 | } 20 | /* with an optional */ 21 | @container tall (height > 30rem) { 22 | h2 { 23 | line-height: 1.6; 24 | } 25 | } 26 | .post { 27 | container-name: tall; 28 | container-type: inline-size; 29 | } 30 | /* shorthand syntax */ 31 | .post { 32 | container: tall / inline-size; 33 | } 34 | 35 | @counter-style thumbs { 36 | system: cyclic; 37 | symbols: "\1F44D"; 38 | suffix: " "; 39 | } 40 | ul { 41 | list-style: thumbs; 42 | } 43 | 44 | @font-face { 45 | font-family: "MyWebFont"; 46 | src: url("webfont.woff2") format("woff2"), url("webfont.woff") format("woff"); 47 | } 48 | 49 | @font-feature-values MyFont { 50 | @styleset { 51 | nice-style: 1; 52 | } 53 | @stylistic { 54 | nice-style: 1; 55 | } 56 | @character-variant { 57 | nice-style: 1; 58 | } 59 | @swash { 60 | nice-style: 1; 61 | } 62 | @ornaments { 63 | nice-style: 1; 64 | } 65 | @annotation { 66 | nice-style: 1; 67 | } 68 | } 69 | 70 | @import url("https://fonts.googleapis.com/css?family=Open+Sans"); 71 | 72 | @keyframes slidein { 73 | from { 74 | margin-left: 100%; 75 | width: 300%; 76 | } 77 | to { 78 | margin-left: 0%; 79 | width: 100%; 80 | } 81 | } 82 | 83 | @layer base { 84 | h1 { 85 | color: red; 86 | } 87 | } 88 | 89 | @media (max-width: 600px) { 90 | .facet_sidebar { 91 | display: none; 92 | } 93 | } 94 | @media (min-width: 600px), (orientation: portrait) { 95 | /* Styles */ 96 | } 97 | 98 | @page { 99 | size: A4; 100 | margin: 10%; 101 | } 102 | @page :left { 103 | margin-top: 4in; 104 | } 105 | @page wide { 106 | size: a4 landscape; 107 | } 108 | @page { 109 | /* margin box at top right showing page number */ 110 | @top-right { 111 | content: "Page " counter(pageNumber); 112 | } 113 | } 114 | 115 | /* @property is not cross-browser friendly yet */ 116 | /* @property --my-color { 117 | syntax: ''; 118 | inherits: false; 119 | initial-value: black; 120 | } */ 121 | 122 | /* @scope is not cross-browser friendly yet */ 123 | /* @scope (.article-body) to (figure) { 124 | img { 125 | border: 5px solid black; 126 | background-color: goldenrod; 127 | } 128 | :scope { 129 | background: rebeccapurple; 130 | color: antiquewhite; 131 | font-family: sans-serif; 132 | } 133 | } */ 134 | 135 | @supports (display: grid) { 136 | .grid { 137 | display: grid; 138 | } 139 | } 140 | 141 | /** 142 | * FEATURE QUERY OPERATORS (AND, OR, NOT) 143 | */ 144 | 145 | /* AND */ 146 | @container (width > 400px) and (height > 400px) { 147 | } 148 | @media (min-width: 600px) and (orientation: landscape) { 149 | } 150 | @supports (display: grid) and (gap: 1rem) { 151 | } 152 | 153 | /* NOT */ 154 | @container not (width < 400px) { 155 | } 156 | @media not (orientation: landscape) { 157 | } 158 | @supports not (display: flex) { 159 | } 160 | 161 | /* OR */ 162 | @container (width > 400px) or (height > 400px) { 163 | } 164 | @supports (display: grid) or (display: flex) { 165 | } 166 | 167 | /** 168 | * COMBINATORS 169 | */ 170 | 171 | .example > li { 172 | margin: 0; 173 | } 174 | div > span { 175 | margin: 0; 176 | } 177 | p ~ span { 178 | color: red; 179 | } 180 | img + p { 181 | color: red; 182 | } 183 | 184 | .example { 185 | div { 186 | > span { 187 | margin: 0; 188 | } 189 | } 190 | p { 191 | ~ span { 192 | color: red; 193 | } 194 | } 195 | img { 196 | + p { 197 | color: red; 198 | } 199 | } 200 | } 201 | 202 | .example { 203 | & div { 204 | & > span { 205 | margin: 0; 206 | } 207 | } 208 | & p { 209 | & ~ span { 210 | color: red; 211 | } 212 | } 213 | & img { 214 | & + p { 215 | color: red; 216 | } 217 | } 218 | } 219 | 220 | /** 221 | * COMMAS 222 | */ 223 | 224 | html, 225 | body { 226 | margin: 0; 227 | &.a, 228 | &.b { 229 | margin: 0; 230 | } 231 | } 232 | 233 | @media (prefers-reduced-motion: reduce) { 234 | html, 235 | html:focus-within { 236 | scroll-behavior: auto; 237 | &.a, 238 | &.b { 239 | margin: 0; 240 | } 241 | } 242 | } 243 | 244 | .class, 245 | .example { 246 | @media (min-width: 500px) { 247 | &::before, 248 | &::after { 249 | content: '"'; 250 | display: block; 251 | } 252 | } 253 | } 254 | 255 | .class, 256 | .example { 257 | fieldset, 258 | span { 259 | max-width: calc((768 / 16) * 1rem); 260 | &.class_left, 261 | &.class_right { 262 | flex: 0 0 100%; 263 | } 264 | } 265 | } 266 | 267 | @media only screen and (max-width: calc( (768 / 16) * 1rem )) { 268 | .class, 269 | .example { 270 | fieldset, 271 | span { 272 | max-width: calc((768 / 16) * 1rem); 273 | flex: 0 0 100%; 274 | &.class_left, 275 | &.class_right { 276 | flex: 0 0 100%; 277 | } 278 | } 279 | } 280 | } 281 | 282 | .class, 283 | .example { 284 | @media only screen and (max-width: calc( (768 / 16) * 1rem )) { 285 | fieldset, 286 | span { 287 | max-width: calc((768 / 16) * 1rem); 288 | flex: 0 0 100%; 289 | &.class_left, 290 | &.class_right { 291 | flex: 0 0 100%; 292 | } 293 | } 294 | } 295 | } 296 | 297 | /** 298 | * FUNCTIONS 299 | */ 300 | 301 | .example { 302 | color: rgb(255, 0, 0); 303 | background-color: oklch(70% 0.1 315); 304 | margin-top: calc((100 / 16) * 1rem); 305 | margin-bottom: calc(var(--size, 10px) * 1rem); 306 | max-width: min(100%, 600px); 307 | padding: clamp(1rem, 5%, 2rem); 308 | width: calc(100% - 3em); 309 | } 310 | 311 | /** 312 | * PROPERTY NAMES WHEN SAME AS TAG NAMES 313 | */ 314 | 315 | content, 316 | cursor, 317 | filter, 318 | span { 319 | content: ""; 320 | cursor: pointer; 321 | filter: brightness(1.075); 322 | } 323 | 324 | .class { 325 | &::before { 326 | content: ""; 327 | cursor: pointer; 328 | filter: brightness(1.075); 329 | } 330 | & content, 331 | & cursor, 332 | & filter, 333 | & span { 334 | margin: 0; 335 | } 336 | } 337 | 338 | .class { 339 | span, 340 | header, 341 | nav, 342 | label, 343 | ruby, 344 | mark, 345 | svg { 346 | margin: 0; 347 | } 348 | } 349 | 350 | /** 351 | * PSEUDO CLASS NESTING 352 | */ 353 | 354 | .class { 355 | > :nth-child(1) { 356 | margin: 0; 357 | } 358 | @media screen and (max-width: 1100px) { 359 | > :nth-child(1) { 360 | margin: 0; 361 | > :nth-child(1) { 362 | margin: 0; 363 | } 364 | } 365 | } 366 | } 367 | 368 | /* REFERENCES FOR ADDING ADDITIONAL TYPES */ 369 | /* https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors */ 370 | /* https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes */ 371 | /* https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_pseudo-elements */ 372 | /* https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements */ 373 | 374 | /* 375 | - selectors 376 | - tag-names 377 | - combinators 378 | - functional-pseudo-classes 379 | - pseudo-classes 380 | - pseudo-elements 381 | - urls 382 | - color-keywords 383 | - functions 384 | - timing-function 385 | - keyword.operator.shape 386 | - property-names 387 | - property-values 388 | - property-keywords 389 | - string 390 | */ 391 | -------------------------------------------------------------------------------- /.dev-assets/get-shared-names.js: -------------------------------------------------------------------------------- 1 | (function getSharedNames() { 2 | const propertyNames = 3 | "accent-color|additive-symbols|align-content|align-items|align-self|all|animation|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|backdrop-filter|backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|background-image|background-origin|background-position|background-position-[xy]|background-repeat|background-size|bleed|block-size|border|border-block-end|border-block-end-color|border-block-end-style|border-block-end-width|border-block-start|border-block-start-color|border-block-start-style|border-block-start-width|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-end-end-radius|border-end-start-radius|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-inline-end|border-inline-end-color|border-inline-end-style|border-inline-end-width|border-inline-start|border-inline-start-color|border-inline-start-style|border-inline-start-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-start-end-radius|border-start-start-radius|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|bottom|box-decoration-break|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|caret-color|clear|clip|clip-path|clip-rule|color|color-adjust|color-interpolation-filters|color-scheme|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|contain|container|container-name|container-type|content|counter-increment|counter-reset|cursor|direction|display|empty-cells|enable-background|fallback|fill|fill-opacity|fill-rule|filter|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-shrink|flex-wrap|float|flood-color|flood-opacity|font|font-display|font-family|font-feature-settings|font-kerning|font-language-override|font-optical-sizing|font-size|font-size-adjust|font-stretch|font-style|font-synthesis|font-variant|font-variant-alternates|font-variant-caps|font-variant-east-asian|font-variant-ligatures|font-variant-numeric|font-variant-position|font-variation-settings|font-weight|gap|glyph-orientation-horizontal|glyph-orientation-vertical|grid|grid-area|grid-auto-columns|grid-auto-flow|grid-auto-rows|grid-column|grid-column-end|grid-column-gap|grid-column-start|grid-gap|grid-row|grid-row-end|grid-row-gap|grid-row-start|grid-template|grid-template-areas|grid-template-columns|grid-template-rows|hanging-punctuation|height|hyphens|image-orientation|image-rendering|image-resolution|ime-mode|initial-letter|initial-letter-align|inline-size|inset|inset-block|inset-block-end|inset-block-start|inset-inline|inset-inline-end|inset-inline-start|isolation|justify-content|justify-items|justify-self|kerning|left|letter-spacing|lighting-color|line-break|line-clamp|line-height|list-style|list-style-image|list-style-position|list-style-type|margin|margin-block|margin-block-end|margin-block-start|margin-bottom|margin-inline|margin-inline-end|margin-inline-start|margin-left|margin-right|margin-top|marker-end|marker-mid|marker-start|marks|mask|mask-border|mask-border-mode|mask-border-outset|mask-border-repeat|mask-border-slice|mask-border-source|mask-border-width|mask-clip|mask-composite|mask-image|mask-mode|mask-origin|mask-position|mask-repeat|mask-size|mask-type|max-block-size|max-height|max-inline-size|max-lines|max-width|max-zoom|min-block-size|min-height|min-inline-size|min-width|min-zoom|mix-blend-mode|negative|object-fit|object-position|offset|offset-anchor|offset-distance|offset-path|offset-position|offset-rotation|opacity|order|orientation|orphans|outline|outline-color|outline-offset|outline-style|outline-width|overflow|overflow-anchor|overflow-block|overflow-inline|overflow-wrap|overflow-[xy]|overscroll-behavior|overscroll-behavior-block|overscroll-behavior-inline|overscroll-behavior-[xy]|pad|padding|padding-block|padding-block-end|padding-block-start|padding-bottom|padding-inline|padding-inline-end|padding-inline-start|padding-left|padding-right|padding-top|page-break-after|page-break-before|page-break-inside|paint-order|perspective|perspective-origin|place-content|place-items|place-self|pointer-events|position|prefix|quotes|range|resize|right|rotate|row-gap|ruby-align|ruby-merge|ruby-position|scale|scroll-behavior|scroll-margin|scroll-margin-block|scroll-margin-block-end|scroll-margin-block-start|scroll-margin-bottom|scroll-margin-inline|scroll-margin-inline-end|scroll-margin-inline-start|scroll-margin-left|scroll-margin-right|scroll-margin-top|scroll-padding|scroll-padding-block|scroll-padding-block-end|scroll-padding-block-start|scroll-padding-bottom|scroll-padding-inline|scroll-padding-inline-end|scroll-padding-inline-start|scroll-padding-left|scroll-padding-right|scroll-padding-top|scroll-snap-align|scroll-snap-coordinate|scroll-snap-destination|scroll-snap-stop|scroll-snap-type|scrollbar-color|scrollbar-gutter|scrollbar-width|shape-image-threshold|shape-margin|shape-outside|shape-rendering|size|speak-as|src|stop-color|stop-opacity|stroke|stroke-dasharray|stroke-dashoffset|stroke-linecap|stroke-linejoin|stroke-miterlimit|stroke-opacity|stroke-width|suffix|symbols|system|tab-size|table-layout|text-align|text-align-last|text-anchor|text-combine-upright|text-decoration|text-decoration-color|text-decoration-line|text-decoration-skip|text-decoration-skip-ink|text-decoration-style|text-decoration-thickness|text-emphasis|text-emphasis-color|text-emphasis-position|text-emphasis-style|text-indent|text-justify|text-orientation|text-overflow|text-rendering|text-shadow|text-size-adjust|text-transform|text-underline-offset|text-underline-position|top|touch-action|transform|transform-box|transform-origin|transform-style|transition|transition-delay|transition-duration|transition-property|transition-timing-function|translate|unicode-bidi|unicode-range|user-select|user-zoom|vertical-align|visibility|white-space|widows|width|will-change|word-break|word-spacing|word-wrap|writing-mode|z-index|zoom#SVGattributes|alignment-baseline|baseline-shift|clip-rule|color-interpolation|color-interpolation-filters|color-profile|color-rendering|cx|cy|dominant-baseline|enable-background|fill|fill-opacity|fill-rule|flood-color|flood-opacity|glyph-orientation-horizontal|glyph-orientation-vertical|height|kerning|lighting-color|marker-end|marker-mid|marker-start|r|rx|ry|shape-rendering|stop-color|stop-opacity|stroke|stroke-dasharray|stroke-dashoffset|stroke-linecap|stroke-linejoin|stroke-miterlimit|stroke-opacity|stroke-width|text-anchor|width|x|y#NotlistedonMDN;presumablydeprecated|adjust|after|align|align-last|alignment|alignment-adjust|appearance|attachment|azimuth|background-break|balance|baseline|before|bidi|binding|bookmark|bookmark-label|bookmark-level|bookmark-target|border-length|bottom-color|bottom-left-radius|bottom-right-radius|bottom-style|bottom-width|box|box-align|box-direction|box-flex|box-flex-group|box-lines|box-ordinal-group|box-orient|box-pack|break|character|collapse|column|column-break-after|column-break-before|count|counter|crop|cue|cue-after|cue-before|decoration|decoration-break|delay|display-model|display-role|down|drop|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|duration|elevation|emphasis|family|fit|fit-position|flex-group|float-offset|gap|grid-columns|grid-rows|hanging-punctuation|header|hyphenate|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|icon|image|increment|indent|index|initial-after-adjust|initial-after-align|initial-before-adjust|initial-before-align|initial-size|initial-value|inline-box-align|iteration-count|justify|label|left-color|left-style|left-width|length|level|line|line-stacking|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|lines|list|mark|mark-after|mark-before|marks|marquee|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max|min|model|move-to|name|nav|nav-down|nav-index|nav-left|nav-right|nav-up|new|numeral|offset|ordinal-group|orient|origin|overflow-style|overhang|pack|page|page-policy|pause|pause-after|pause-before|phonemes|pitch|pitch-range|play-count|play-during|play-state|point|presentation|presentation-level|profile|property|punctuation|punctuation-trim|radius|rate|rendering-intent|repeat|replace|reset|resolution|resource|respond-to|rest|rest-after|rest-before|richness|right-color|right-style|right-width|role|rotation|rotation-point|rows|ruby|ruby-overhang|ruby-span|rule|rule-color|rule-style|rule-width|shadow|size|size-adjust|sizing|space|space-collapse|spacing|span|speak|speak-header|speak-numeral|speak-punctuation|speech|speech-rate|speed|stacking|stacking-ruby|stacking-shift|stacking-strategy|stress|stretch|string-set|style|style-image|style-position|style-type|target|target-name|target-new|target-position|text|text-height|text-justify|text-outline|text-replace|text-wrap|timing-function|top-color|top-left-radius|top-right-radius|top-style|top-width|trim|unicode|up|user-select|variant|voice|voice-balance|voice-duration|voice-family|voice-pitch|voice-pitch-range|voice-rate|voice-stress|voice-volume|volume|weight|white|white-space-collapse|word|wrap"; 4 | 5 | const tagNames = 6 | "a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|bgsound|big|blink|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|command|content|data|datalist|dd|del|details|dfn|dialog|dir|div|dl|dt|element|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h[1-6]|head|header|hgroup|hr|html|i|iframe|image|img|input|ins|isindex|kbd|keygen|label|legend|li|link|listing|main|map|mark|marquee|math|menu|menuitem|meta|meter|multicol|nav|nextid|nobr|noembed|noframes|noscript|object|ol|optgroup|option|output|p|param|picture|plaintext|pre|progress|q|rb|rp|rt|rtc|ruby|s|samp|script|section|select|shadow|slot|small|source|spacer|span|strike|strong|style|sub|summary|sup|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr|xmp#SVG|altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|use|view|vkern#MathML|annotation|annotation-xml|maction|maligngroup|malignmark|math|menclose|merror|mfenced|mfrac|mglyph|mi|mlabeledtr|mlongdiv|mmultiscripts|mn|mo|mover|mpadded|mphantom|mroot|mrow|ms|mscarries|mscarry|msgroup|msline|mspace|msqrt|msrow|mstack|mstyle|msub|msubsup|msup|mtable|mtd|mtext|mtr|munder|munderover|semantics"; 7 | 8 | const propertyNamesArray = propertyNames.split("|"); 9 | const tagNamesArray = tagNames.split("|"); 10 | const testSet = new Set(propertyNamesArray); 11 | const sharedWords = tagNamesArray.filter((item) => testSet.has(item)).sort(); 12 | 13 | console.log(sharedWords); 14 | 15 | // LOGS: 16 | // color-profile 17 | // content 18 | // cursor P 19 | // filter 20 | // font 21 | // header 22 | // image 23 | // label 24 | // line 25 | // mark 26 | // marquee 27 | // mask 28 | // nav 29 | // ruby 30 | // shadow 31 | // span 32 | // style 33 | // text 34 | 35 | // HTML TAGS FROM LIST ABOVE: 36 | // content 37 | // font 38 | // header 39 | // image 40 | // label 41 | // mark 42 | // marquee 43 | // mask 44 | // nav 45 | // ruby 46 | // shadow 47 | // span 48 | // style 49 | 50 | // SVG TAGS FROM LIST ABOVE: 51 | // color-profile 52 | // cursor 53 | // filter 54 | // line 55 | // text 56 | 57 | })(); 58 | -------------------------------------------------------------------------------- /syntaxes/css.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "information_for_contributors": [ 3 | "This file has been converted from https://github.com/microsoft/vscode-css/blob/master/grammars/css.cson", 4 | "If you want to provide a fix or improvement, please create a pull request against the original repository.", 5 | "Once accepted there, we are happy to receive an update request." 6 | ], 7 | "version": "https://github.com/microsoft/vscode-css/commit/c216f777497265700ff336f739328e5197e012cd", 8 | "name": "CSS", 9 | "scopeName": "source.css", 10 | "patterns": [ 11 | { 12 | "include": "#comment-block" 13 | }, 14 | { 15 | "include": "#escapes" 16 | }, 17 | { 18 | "include": "#combinators" 19 | }, 20 | { 21 | "include": "#selector" 22 | }, 23 | { 24 | "include": "#at-rules" 25 | }, 26 | { 27 | "include": "#rule-list" 28 | }, 29 | { 30 | "include": "#nesting-selector" 31 | } 32 | ], 33 | "repository": { 34 | "arithmetic-operators": { 35 | "match": "[*/]|(?<=\\s|^)[-+](?=\\s|$)", 36 | "name": "keyword.operator.arithmetic.css" 37 | }, 38 | "at-rules": { 39 | "patterns": [ 40 | { 41 | "begin": "(?i)(?=@container(\\s|\\(|/\\*|$))", 42 | "end": "(?<=})(?!\\G)", 43 | "patterns": [ 44 | { 45 | "begin": "(?i)\\G(@)container", 46 | "beginCaptures": { 47 | "0": { 48 | "name": "keyword.control.at-rule.container.css" 49 | }, 50 | "1": { 51 | "name": "punctuation.definition.keyword.css" 52 | } 53 | }, 54 | "end": "(?=\\s*[{;])", 55 | "name": "meta.at-rule.container.header.css", 56 | "patterns": [ 57 | { 58 | "include": "#container-condition" 59 | } 60 | ] 61 | }, 62 | { 63 | "begin": "{", 64 | "beginCaptures": { 65 | "0": { 66 | "name": "punctuation.section.container.begin.bracket.curly.css" 67 | } 68 | }, 69 | "end": "}", 70 | "endCaptures": { 71 | "0": { 72 | "name": "punctuation.section.container.end.bracket.curly.css" 73 | } 74 | }, 75 | "name": "meta.at-rule.container.body.css", 76 | "patterns": [ 77 | { 78 | "include": "#nesting-at-rules" 79 | }, 80 | { 81 | "include": "$self" 82 | } 83 | ] 84 | } 85 | ] 86 | }, 87 | { 88 | "begin": "\\A(?:\\xEF\\xBB\\xBF)?(?i:(?=\\s*@charset\\b))", 89 | "end": ";|(?=$)", 90 | "endCaptures": { 91 | "0": { 92 | "name": "punctuation.terminator.rule.css" 93 | } 94 | }, 95 | "name": "meta.at-rule.charset.css", 96 | "patterns": [ 97 | { 98 | "captures": { 99 | "1": { 100 | "name": "invalid.illegal.not-lowercase.charset.css" 101 | }, 102 | "2": { 103 | "name": "invalid.illegal.leading-whitespace.charset.css" 104 | }, 105 | "3": { 106 | "name": "invalid.illegal.no-whitespace.charset.css" 107 | }, 108 | "4": { 109 | "name": "invalid.illegal.whitespace.charset.css" 110 | }, 111 | "5": { 112 | "name": "invalid.illegal.not-double-quoted.charset.css" 113 | }, 114 | "6": { 115 | "name": "invalid.illegal.unclosed-string.charset.css" 116 | }, 117 | "7": { 118 | "name": "invalid.illegal.unexpected-characters.charset.css" 119 | } 120 | }, 121 | "match": "(?x) # Possible errors:\n\\G\n((?!@charset)@\\w+) # Not lowercase (@charset is case-sensitive)\n|\n\\G(\\s+) # Preceding whitespace\n|\n(@charset\\S[^;]*) # No whitespace after @charset\n|\n(?<=@charset) # Before quoted charset name\n(\\x20{2,}|\\t+) # More than one space used, or a tab\n|\n(?<=@charset\\x20) # Beginning of charset name\n([^\";]+) # Not double-quoted\n|\n(\"[^\"]+$) # Unclosed quote\n|\n(?<=\") # After charset name\n([^;]+) # Unexpected junk instead of semicolon" 122 | }, 123 | { 124 | "captures": { 125 | "1": { 126 | "name": "keyword.control.at-rule.charset.css" 127 | }, 128 | "2": { 129 | "name": "punctuation.definition.keyword.css" 130 | } 131 | }, 132 | "match": "((@)charset)(?=\\s)" 133 | }, 134 | { 135 | "begin": "\"", 136 | "beginCaptures": { 137 | "0": { 138 | "name": "punctuation.definition.string.begin.css" 139 | } 140 | }, 141 | "end": "\"|$", 142 | "endCaptures": { 143 | "0": { 144 | "name": "punctuation.definition.string.end.css" 145 | } 146 | }, 147 | "name": "string.quoted.double.css", 148 | "patterns": [ 149 | { 150 | "begin": "(?:\\G|^)(?=(?:[^\"])+$)", 151 | "end": "$", 152 | "name": "invalid.illegal.unclosed.string.css" 153 | } 154 | ] 155 | } 156 | ] 157 | }, 158 | { 159 | "begin": "(?i)((@)import)(?:\\s+|$|(?=['\"]|/\\*))", 160 | "beginCaptures": { 161 | "1": { 162 | "name": "keyword.control.at-rule.import.css" 163 | }, 164 | "2": { 165 | "name": "punctuation.definition.keyword.css" 166 | } 167 | }, 168 | "end": ";", 169 | "endCaptures": { 170 | "0": { 171 | "name": "punctuation.terminator.rule.css" 172 | } 173 | }, 174 | "name": "meta.at-rule.import.css", 175 | "patterns": [ 176 | { 177 | "begin": "\\G\\s*(?=/\\*)", 178 | "end": "(?<=\\*/)\\s*", 179 | "patterns": [ 180 | { 181 | "include": "#comment-block" 182 | } 183 | ] 184 | }, 185 | { 186 | "include": "#string" 187 | }, 188 | { 189 | "include": "#url" 190 | }, 191 | { 192 | "include": "#media-query-list" 193 | } 194 | ] 195 | }, 196 | { 197 | "begin": "(?i)((@)font-face)(?=\\s*|{|/\\*|$)", 198 | "beginCaptures": { 199 | "1": { 200 | "name": "keyword.control.at-rule.font-face.css" 201 | }, 202 | "2": { 203 | "name": "punctuation.definition.keyword.css" 204 | } 205 | }, 206 | "end": "(?!\\G)", 207 | "name": "meta.at-rule.font-face.css", 208 | "patterns": [ 209 | { 210 | "include": "#comment-block" 211 | }, 212 | { 213 | "include": "#escapes" 214 | }, 215 | { 216 | "include": "#rule-list" 217 | } 218 | ] 219 | }, 220 | { 221 | "begin": "(?i)(@)page(?=[\\s:{]|/\\*|$)", 222 | "captures": { 223 | "0": { 224 | "name": "keyword.control.at-rule.page.css" 225 | }, 226 | "1": { 227 | "name": "punctuation.definition.keyword.css" 228 | } 229 | }, 230 | "end": "(?=\\s*($|[:{;]))", 231 | "name": "meta.at-rule.page.css", 232 | "patterns": [ 233 | { 234 | "include": "#rule-list" 235 | } 236 | ] 237 | }, 238 | { 239 | "begin": "(?i)(?=@media(\\s|\\(|/\\*|$))", 240 | "end": "(?<=})(?!\\G)", 241 | "patterns": [ 242 | { 243 | "begin": "(?i)\\G(@)media", 244 | "beginCaptures": { 245 | "0": { 246 | "name": "keyword.control.at-rule.media.css" 247 | }, 248 | "1": { 249 | "name": "punctuation.definition.keyword.css" 250 | } 251 | }, 252 | "end": "(?=\\s*[{;])", 253 | "name": "meta.at-rule.media.header.css", 254 | "patterns": [ 255 | { 256 | "include": "#media-query-list" 257 | } 258 | ] 259 | }, 260 | { 261 | "begin": "{", 262 | "beginCaptures": { 263 | "0": { 264 | "name": "punctuation.section.media.begin.bracket.curly.css" 265 | } 266 | }, 267 | "end": "}", 268 | "endCaptures": { 269 | "0": { 270 | "name": "punctuation.section.media.end.bracket.curly.css" 271 | } 272 | }, 273 | "name": "meta.at-rule.media.body.css", 274 | "patterns": [ 275 | { 276 | "include": "#nesting-at-rules" 277 | }, 278 | { 279 | "include": "$self" 280 | } 281 | ] 282 | } 283 | ] 284 | }, 285 | { 286 | "begin": "(?i)(?=@counter-style([\\s'\"{;]|/\\*|$))", 287 | "end": "(?<=})(?!\\G)", 288 | "patterns": [ 289 | { 290 | "begin": "(?i)\\G(@)counter-style", 291 | "beginCaptures": { 292 | "0": { 293 | "name": "keyword.control.at-rule.counter-style.css" 294 | }, 295 | "1": { 296 | "name": "punctuation.definition.keyword.css" 297 | } 298 | }, 299 | "end": "(?=\\s*{)", 300 | "name": "meta.at-rule.counter-style.header.css", 301 | "patterns": [ 302 | { 303 | "include": "#comment-block" 304 | }, 305 | { 306 | "include": "#escapes" 307 | }, 308 | { 309 | "captures": { 310 | "0": { 311 | "patterns": [ 312 | { 313 | "include": "#escapes" 314 | } 315 | ] 316 | } 317 | }, 318 | "match": "(?x)\n(?:[-a-zA-Z_] | [^\\x00-\\x7F]) # First letter\n(?:[-a-zA-Z0-9_] | [^\\x00-\\x7F] # Remainder of identifier\n |\\\\(?:[0-9a-fA-F]{1,6}|.)\n)*", 319 | "name": "variable.parameter.style-name.css" 320 | } 321 | ] 322 | }, 323 | { 324 | "begin": "{", 325 | "beginCaptures": { 326 | "0": { 327 | "name": "punctuation.section.property-list.begin.bracket.curly.css" 328 | } 329 | }, 330 | "end": "}", 331 | "endCaptures": { 332 | "0": { 333 | "name": "punctuation.section.property-list.end.bracket.curly.css" 334 | } 335 | }, 336 | "name": "meta.at-rule.counter-style.body.css", 337 | "patterns": [ 338 | { 339 | "include": "#comment-block" 340 | }, 341 | { 342 | "include": "#escapes" 343 | }, 344 | { 345 | "include": "#rule-list-innards" 346 | } 347 | ] 348 | } 349 | ] 350 | }, 351 | { 352 | "begin": "(?i)(?=@document([\\s'\"{;]|/\\*|$))", 353 | "end": "(?<=})(?!\\G)", 354 | "patterns": [ 355 | { 356 | "begin": "(?i)\\G(@)document", 357 | "beginCaptures": { 358 | "0": { 359 | "name": "keyword.control.at-rule.document.css" 360 | }, 361 | "1": { 362 | "name": "punctuation.definition.keyword.css" 363 | } 364 | }, 365 | "end": "(?=\\s*[{;])", 366 | "name": "meta.at-rule.document.header.css", 367 | "patterns": [ 368 | { 369 | "begin": "(?i)(?>>", 760 | "name": "invalid.deprecated.combinator.css" 761 | }, 762 | { 763 | "match": ">>|>|\\+|~", 764 | "name": "keyword.operator.combinator.css" 765 | } 766 | ] 767 | }, 768 | "commas": { 769 | "match": ",", 770 | "name": "punctuation.separator.list.comma.css" 771 | }, 772 | "comment-block": { 773 | "begin": "/\\*", 774 | "beginCaptures": { 775 | "0": { 776 | "name": "punctuation.definition.comment.begin.css" 777 | } 778 | }, 779 | "end": "\\*/", 780 | "endCaptures": { 781 | "0": { 782 | "name": "punctuation.definition.comment.end.css" 783 | } 784 | }, 785 | "name": "comment.block.css" 786 | }, 787 | "container-condition": { 788 | "begin": "\\G", 789 | "end": "(?=\\s*[{;])", 790 | "patterns": [ 791 | { 792 | "include": "#comment-block" 793 | }, 794 | { 795 | "include": "#escapes" 796 | }, 797 | { 798 | "match": "(?xi)\n (?<=not.*)not\n # Only one `not` in allowed", 799 | "name": "invalid.illegal.multiple-not.container.css" 800 | }, 801 | { 802 | "match": "(?i)(?<=\\s|^|,|\\*/)(and|or|not)(?=\\s|{|/\\*|$)", 803 | "name": "keyword.operator.logical.$1.container.css" 804 | }, 805 | { 806 | "include": "#container-name" 807 | }, 808 | { 809 | "include": "#container-query" 810 | } 811 | ] 812 | }, 813 | "container-name": { 814 | "begin": "\\G", 815 | "end": "(?xi)\n (?=(?:\\(|not)|style\\()\n # Ends when `(`, `not`, or `style(` is reached", 816 | "patterns": [ 817 | { 818 | "include": "#comment-block" 819 | }, 820 | { 821 | "captures": { 822 | "1": { 823 | "name": "invalid.illegal.constant.container-name.container.css" 824 | }, 825 | "2": { 826 | "name": "support.constant.container-name.container.css" 827 | } 828 | }, 829 | "match": "(?xi)\n (?<=^|\\s|\\*/)\n(?:\n # Invalid name\n (default|none)\n |\n # Valid names\n ([a-zA-Z0-9\\-_\\\\]+)\n )\n(?=$|[({\\s;]|/\\*)" 830 | } 831 | ] 832 | }, 833 | "container-query": { 834 | "begin": "((?<=\\s)\\()|(style)(\\()", 835 | "beginCaptures": { 836 | "1": { 837 | "name": "punctuation.definition.parameters.begin.bracket.round.css" 838 | }, 839 | "2": { 840 | "name": "support.style-query.container.css" 841 | }, 842 | "3": { 843 | "name": "punctuation.definition.parameters.begin.bracket.round.css" 844 | } 845 | }, 846 | "end": "\\)", 847 | "endCaptures": { 848 | "0": { 849 | "name": "punctuation.definition.parameters.end.bracket.round.css" 850 | } 851 | }, 852 | "patterns": [ 853 | { 854 | "begin": "(?xi)\n (?<=\\s\\()\n # Rules for size ", 855 | "end": "(?=\\))", 856 | "patterns": [ 857 | { 858 | "include": "#container-query-features" 859 | }, 860 | { 861 | "include": "#container-size-features" 862 | }, 863 | { 864 | "include": "#container-size-feature-keywords" 865 | } 866 | ] 867 | }, 868 | { 869 | "begin": "(?xi)\n (?<=style\\()\n # Rules for container-query ", 870 | "end": "(?=\\))", 871 | "name": "style-query.container.css", 872 | "patterns": [ 873 | { 874 | "include": "#container-query-features" 875 | }, 876 | { 877 | "include": "#container-style-features" 878 | }, 879 | { 880 | "include": "#container-style-feature-keywords" 881 | } 882 | ] 883 | } 884 | ] 885 | }, 886 | "container-query-features": { 887 | "patterns": [ 888 | { 889 | "match": ":", 890 | "name": "punctuation.separator.key-value.css" 891 | }, 892 | { 893 | "match": ">=|<=|=|<|>", 894 | "name": "keyword.operator.comparison.css" 895 | }, 896 | { 897 | "include": "#numeric-values" 898 | }, 899 | { 900 | "include": "#comment-block" 901 | } 902 | ] 903 | }, 904 | "container-size-features": { 905 | "match": "(?xi)\n (?<=^|\\s|\\(|\\*/) # Preceded by whitespace, bracket or comment\n (?:\n # Standardised features\n (\n (?:min-|max-)? # Range features\n (?: aspect-ratio\n | block-size\n | height\n | inline-size\n | width\n )\n | orientation\n )\n )\n (?=\\s|$|[><:=]|\\)|/\\*) # Terminates cleanly", 906 | "name": "support.size.property-name.container.css" 907 | }, 908 | "container-size-feature-keywords": { 909 | "patterns": [ 910 | { 911 | "match": "(?xi)\n (?<=^|\\s|:|\\*/)\n # Preceded by whitespace, colon, or comment\n (?: portrait\n | landscape\n # Orientation\n )\n (?=\\s|\\)|$)", 912 | "name": "support.constant.property-value.container.css" 913 | }, 914 | { 915 | "include": "#functions" 916 | } 917 | ] 918 | }, 919 | "container-style-features": { 920 | "match": "(?x)\n # Custom Property Name\n (?<=^|\\s|\\(|\\*/) # Preceded by whitespace, bracket or comment\n (?<:=]|\\)|/\\*) # Terminates cleanly" 1525 | }, 1526 | "media-feature-keywords": { 1527 | "match": "(?xi)\n(?<=^|\\s|:|\\*/)\n(?: portrait # Orientation\n | landscape\n | progressive # Scan types\n | interlace\n | fullscreen # Display modes\n | standalone\n | minimal-ui\n | browser\n | hover\n)\n(?=\\s|\\)|$)", 1528 | "name": "support.constant.property-value.css" 1529 | }, 1530 | "media-query": { 1531 | "begin": "\\G", 1532 | "end": "(?=\\s*[{;])", 1533 | "patterns": [ 1534 | { 1535 | "include": "#comment-block" 1536 | }, 1537 | { 1538 | "include": "#escapes" 1539 | }, 1540 | { 1541 | "include": "#media-types" 1542 | }, 1543 | { 1544 | "match": "(?i)(?<=\\s|^|,|\\*/)(only|not)(?=\\s|{|/\\*|$)", 1545 | "name": "keyword.operator.logical.$1.media.css" 1546 | }, 1547 | { 1548 | "match": "(?i)(?<=\\s|^|\\*/|\\))and(?=\\s|/\\*|$)", 1549 | "name": "keyword.operator.logical.and.media.css" 1550 | }, 1551 | { 1552 | "match": ",(?:(?:\\s*,)+|(?=\\s*[;){]))", 1553 | "name": "invalid.illegal.comma.css" 1554 | }, 1555 | { 1556 | "include": "#commas" 1557 | }, 1558 | { 1559 | "begin": "\\(", 1560 | "beginCaptures": { 1561 | "0": { 1562 | "name": "punctuation.definition.parameters.begin.bracket.round.css" 1563 | } 1564 | }, 1565 | "end": "\\)", 1566 | "endCaptures": { 1567 | "0": { 1568 | "name": "punctuation.definition.parameters.end.bracket.round.css" 1569 | } 1570 | }, 1571 | "patterns": [ 1572 | { 1573 | "include": "#media-features" 1574 | }, 1575 | { 1576 | "include": "#media-feature-keywords" 1577 | }, 1578 | { 1579 | "match": ":", 1580 | "name": "punctuation.separator.key-value.css" 1581 | }, 1582 | { 1583 | "match": ">=|<=|=|<|>", 1584 | "name": "keyword.operator.comparison.css" 1585 | }, 1586 | { 1587 | "captures": { 1588 | "1": { 1589 | "name": "constant.numeric.css" 1590 | }, 1591 | "2": { 1592 | "name": "keyword.operator.arithmetic.css" 1593 | }, 1594 | "3": { 1595 | "name": "constant.numeric.css" 1596 | } 1597 | }, 1598 | "match": "(\\d+)\\s*(/)\\s*(\\d+)", 1599 | "name": "meta.ratio.css" 1600 | }, 1601 | { 1602 | "include": "#numeric-values" 1603 | }, 1604 | { 1605 | "include": "#comment-block" 1606 | }, 1607 | { 1608 | "include": "#functions" 1609 | } 1610 | ] 1611 | } 1612 | ] 1613 | }, 1614 | "media-query-list": { 1615 | "begin": "(?=\\s*[^{;])", 1616 | "end": "(?=\\s*[{;])", 1617 | "patterns": [ 1618 | { 1619 | "include": "#media-query" 1620 | } 1621 | ] 1622 | }, 1623 | "media-types": { 1624 | "captures": { 1625 | "1": { 1626 | "name": "support.constant.media.css" 1627 | }, 1628 | "2": { 1629 | "name": "invalid.deprecated.constant.media.css" 1630 | } 1631 | }, 1632 | "match": "(?xi)\n(?<=^|\\s|,|\\*/)\n(?:\n # Valid media types\n (all|print|screen|speech)\n |\n # Deprecated in Media Queries 4: http://dev.w3.org/csswg/mediaqueries/#media-types\n (aural|braille|embossed|handheld|projection|tty|tv)\n)\n(?=$|[{,\\s;]|/\\*)" 1633 | }, 1634 | "nesting-at-rules": { 1635 | "patterns": [ 1636 | { 1637 | "include": "#commas" 1638 | }, 1639 | { 1640 | "include": "#nesting-rules" 1641 | }, 1642 | { 1643 | "include": "#rule-list-innards" 1644 | } 1645 | ] 1646 | }, 1647 | "nesting-rules": { 1648 | "patterns": [ 1649 | { 1650 | "match": "(?xi) (?\\s,.\\#|&){:\\[]|/\\*|$)", 1651 | "name": "entity.name.tag.css" 1652 | }, 1653 | { 1654 | "include": "#property-names" 1655 | }, 1656 | { 1657 | "include": "#selector-innards" 1658 | } 1659 | ] 1660 | }, 1661 | "nesting-selector": { 1662 | "match": "&", 1663 | "name": "entity.name.tag.nesting.selector.css" 1664 | }, 1665 | "numeric-values": { 1666 | "patterns": [ 1667 | { 1668 | "captures": { 1669 | "1": { 1670 | "name": "punctuation.definition.constant.css" 1671 | } 1672 | }, 1673 | "match": "(#)(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\\b", 1674 | "name": "constant.other.color.rgb-value.hex.css" 1675 | }, 1676 | { 1677 | "captures": { 1678 | "1": { 1679 | "name": "keyword.other.unit.percentage.css" 1680 | }, 1681 | "2": { 1682 | "name": "keyword.other.unit.${2:/downcase}.css" 1683 | } 1684 | }, 1685 | "match": "(?xi) (?+~|&] # - Followed by another selector\n | /\\* # - Followed by a block comment\n )\n |\n # Name contains unescaped ASCII symbol\n (?: # Check for acceptable preceding characters\n [-a-zA-Z_0-9]|[^\\x00-\\x7F] # - Valid selector character\n | \\\\(?:[0-9a-fA-F]{1,6}|.) # - Escape sequence\n )*\n (?: # Invalid punctuation\n [!\"'%(*;+~|&] # - Another selector\n | /\\* # - A block comment\n)", 1936 | "name": "entity.other.attribute-name.class.css" 1937 | }, 1938 | { 1939 | "captures": { 1940 | "1": { 1941 | "name": "punctuation.definition.entity.css" 1942 | }, 1943 | "2": { 1944 | "patterns": [ 1945 | { 1946 | "include": "#escapes" 1947 | } 1948 | ] 1949 | } 1950 | }, 1951 | "match": "(?x)\n(\\#)\n(\n -?\n (?![0-9])\n (?:[-a-zA-Z0-9_]|[^\\x00-\\x7F]|\\\\(?:[0-9a-fA-F]{1,6}|.))+\n)\n(?=$|[\\s,.\\#)\\[:{>+~|&]|/\\*)", 1952 | "name": "entity.other.attribute-name.id.css" 1953 | }, 1954 | { 1955 | "begin": "\\[", 1956 | "beginCaptures": { 1957 | "0": { 1958 | "name": "punctuation.definition.entity.begin.bracket.square.css" 1959 | } 1960 | }, 1961 | "end": "\\]", 1962 | "endCaptures": { 1963 | "0": { 1964 | "name": "punctuation.definition.entity.end.bracket.square.css" 1965 | } 1966 | }, 1967 | "name": "meta.attribute-selector.css", 1968 | "patterns": [ 1969 | { 1970 | "include": "#comment-block" 1971 | }, 1972 | { 1973 | "include": "#string" 1974 | }, 1975 | { 1976 | "captures": { 1977 | "1": { 1978 | "name": "storage.modifier.ignore-case.css" 1979 | } 1980 | }, 1981 | "match": "(?<=[\"'\\s]|^|\\*/)\\s*([iI])\\s*(?=[\\s\\]]|/\\*|$)" 1982 | }, 1983 | { 1984 | "captures": { 1985 | "1": { 1986 | "name": "string.unquoted.attribute-value.css", 1987 | "patterns": [ 1988 | { 1989 | "include": "#escapes" 1990 | } 1991 | ] 1992 | } 1993 | }, 1994 | "match": "(?x)(?<==)\\s*((?!/\\*)(?:[^\\\\\"'\\s\\]]|\\\\.)+)" 1995 | }, 1996 | { 1997 | "include": "#escapes" 1998 | }, 1999 | { 2000 | "match": "[~|^$*]?=", 2001 | "name": "keyword.operator.pattern.css" 2002 | }, 2003 | { 2004 | "match": "\\|", 2005 | "name": "punctuation.separator.css" 2006 | }, 2007 | { 2008 | "captures": { 2009 | "1": { 2010 | "name": "entity.other.namespace-prefix.css", 2011 | "patterns": [ 2012 | { 2013 | "include": "#escapes" 2014 | } 2015 | ] 2016 | } 2017 | }, 2018 | "match": "(?x)\n# Qualified namespace prefix\n( -?(?!\\d)(?:[\\w-]|[^\\x00-\\x7F]|\\\\(?:[0-9a-fA-F]{1,6}|.))+\n| \\*\n)\n# Lookahead to ensure there's a valid identifier ahead\n(?=\n \\| (?!\\s|=|$|\\])\n (?: -?(?!\\d)\n | [\\\\\\w-]\n | [^\\x00-\\x7F]\n )\n)" 2019 | }, 2020 | { 2021 | "captures": { 2022 | "1": { 2023 | "name": "entity.other.attribute-name.css", 2024 | "patterns": [ 2025 | { 2026 | "include": "#escapes" 2027 | } 2028 | ] 2029 | } 2030 | }, 2031 | "match": "(?x)\n(-?(?!\\d)(?>[\\w-]|[^\\x00-\\x7F]|\\\\(?:[0-9a-fA-F]{1,6}|.))+)\n\\s*\n(?=[~|^\\]$*=]|/\\*)" 2032 | } 2033 | ] 2034 | }, 2035 | { 2036 | "include": "#pseudo-classes" 2037 | }, 2038 | { 2039 | "include": "#pseudo-elements" 2040 | }, 2041 | { 2042 | "include": "#functional-pseudo-classes" 2043 | }, 2044 | { 2045 | "match": "(?x) (?\\s,.\\#|&){:\\[]|/\\*|$)", 2116 | "name": "entity.name.tag.css" 2117 | }, 2118 | "unicode-range": { 2119 | "captures": { 2120 | "0": { 2121 | "name": "constant.other.unicode-range.css" 2122 | }, 2123 | "1": { 2124 | "name": "punctuation.separator.dash.unicode-range.css" 2125 | } 2126 | }, 2127 | "match": "(?