From b4decd94594c35d508c24aeba9a5953c992ba6aa Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 18 Feb 2024 08:29:58 +0100 Subject: [PATCH] [CSS] Relaxed Nesting Support (#3898) * [CSS] Relaxed Nesting This commit implements relaxed syntax for nested style rules according to https://www.w3.org/TR/css-nesting-1/#nested-style-rule. In general it means, nested selectors of nested style rules no longer need to start with `&` operator to denote html tags. The implementation adopts `properties-or-selectors` context from Less syntax to achieve reliable distinction between declarations and selectors without loosing support for interpolation. * [CSS] Rename style-block to avoid confusion This commit renames `style-block` contexts to `stylesheet-block` in order to avoid confusion with official syntax specs, because a `style-block` is actually what is represented by `property-lists` contexts in this syntax definition. A stylesheet block's content is however equal to top-level content, which does not support declarations (property-value pairs). * [CSS] Fix ASP/PHP/... interpolation * [CSS] Tiny optimization --- CSS/CSS.sublime-syntax | 68 +++++++++++++++++++++++++---------------- CSS/syntax_test_css.css | 33 +++++++++++--------- 2 files changed, 61 insertions(+), 40 deletions(-) diff --git a/CSS/CSS.sublime-syntax b/CSS/CSS.sublime-syntax index 3d2210e13e..23510b258c 100644 --- a/CSS/CSS.sublime-syntax +++ b/CSS/CSS.sublime-syntax @@ -81,12 +81,12 @@ variables: logical_operators: (?i:and|or|not|only) - # Selectors - selector_begin: (?={{selector_start}}) + # Properties and Selectors + property_or_selector_begin: (?={{ident_begin}}|{{selector_start}}) + property_end: (?=[;@)}]) + + selector_start: '[[:alpha:].:#&*\[{{combinator_char}}]' selector_end: (?=[;@(){}]) - selector_start: '[[:alpha:]{{nested_selector_start}}]' - nested_selector_begin: (?={{nested_selector_start}}) - nested_selector_start: '[.:#&*\[{{combinator_char}}]' keyframe_selector_begin: (?=\b(?i:from|to){{break}}|\.?[\d,%]) @@ -335,6 +335,7 @@ contexts: - include: stylesheet stylesheet: + # https://www.w3.org/TR/css-syntax-3/#typedef-stylesheet - include: comments - include: property-lists - include: selectors @@ -442,7 +443,7 @@ contexts: 1: punctuation.definition.keyword.css push: - at-container-meta - - maybe-style-block + - maybe-stylesheet-block - container-query - at-container-identifier @@ -572,7 +573,7 @@ contexts: 1: punctuation.definition.keyword.css push: - at-document-meta - - maybe-style-block + - maybe-stylesheet-block - at-document-query at-document-meta: @@ -710,7 +711,7 @@ contexts: 1: punctuation.definition.keyword.css push: - at-layer-meta - - maybe-style-block + - maybe-stylesheet-block - at-layer-name-list nested-at-layer: @@ -768,7 +769,7 @@ contexts: 1: punctuation.definition.keyword.css push: - at-media-meta - - maybe-style-block + - maybe-stylesheet-block - media-query-list nested-at-media: @@ -933,7 +934,7 @@ contexts: 1: punctuation.definition.keyword.css push: - at-supports-meta - - maybe-style-block + - maybe-stylesheet-block - at-supports-query nested-at-supports: @@ -1154,12 +1155,7 @@ contexts: ###[ SELECTORS ]############################################################### selectors: - - match: '{{selector_begin}}' - push: selector-body - - nested-selectors: - # https://drafts.csswg.org/css-nesting-1 - - match: '{{nested_selector_begin}}' + - match: '{{property_or_selector_begin}}' push: selector-body selector-body: @@ -1482,19 +1478,17 @@ contexts: fail: pseudo-element - include: identifier-content -###[ STYLE BLOCKS ]############################################################ +###[ STYLESHEET BLOCKS ]####################################################### - maybe-style-block: - # https://www.w3.org/TR/css-syntax-3/#declaration-rule-list - # https://www.w3.org/TR/css-syntax-3/#typedef-style-block + maybe-stylesheet-block: - meta_include_prototype: false - match: \{ scope: punctuation.section.block.begin.css - set: style-block-body + set: stylesheet-block-body - include: comments - include: else-pop - style-block-body: + stylesheet-block-body: - meta_include_prototype: false - meta_scope: meta.block.css - include: block-end @@ -1516,13 +1510,15 @@ contexts: push: property-list-body property-list-body: + # According to official specs, this is a style-block. + # It supports declarations, nested style-rules and at-rules. + # https://www.w3.org/TR/css-syntax-3/#typedef-style-block - meta_include_prototype: false - meta_scope: meta.property-list.css meta.block.css - include: block-end - include: comments - include: property-lists - - include: property-identifiers - - include: nested-selectors + - include: properties-or-selectors - include: nested-at-rules - include: rule-terminators - include: illegal-commas @@ -1530,7 +1526,9 @@ contexts: rule-list-body: # Note: This context is used by HTML.sublime-syntax - # No selectors supported in style attributes. + # According to official specs, this is a declaration-list without support + # for at-rules as inline html attributes don't support them. + # https://www.w3.org/TR/css-syntax-3/#typedef-declaration-list - include: comments - include: property-identifiers - include: property-values @@ -1541,6 +1539,24 @@ contexts: ###[ PROPERTY IDENTIFIERS ]#################################################### + properties-or-selectors: + - match: '{{property_or_selector_begin}}' + branch_point: property-or-selector + branch: + - maybe-property + - selector-body + + maybe-property: + - meta_include_prototype: false + - include: property-end + - include: property-identifiers + - match: '' + fail: property-or-selector + + property-end: + - match: '{{property_end}}' + pop: 1 + property-identifiers: # specific properties with special treatment - include: counter-properties @@ -2917,7 +2933,7 @@ contexts: # Qualified Names # https://drafts.csswg.org/css-namespaces-3/#css-qnames attr-name: - - match: (?=[*|]|--|-?{{ident_start}}) + - match: (?=[*|]|{{ident_begin}}) set: attr-name-content attr-name-content: diff --git a/CSS/syntax_test_css.css b/CSS/syntax_test_css.css index af8ee09953..b0afd360c0 100644 --- a/CSS/syntax_test_css.css +++ b/CSS/syntax_test_css.css @@ -717,7 +717,7 @@ /* ^^ meta.property-list.css meta.block.css - meta.at-rule */ /* ^^^^^^^^^^^^^^^^ meta.property-list.css meta.block.css meta.at-rule.container.css - meta.group - meta.block meta.block */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.container.css meta.block.css - meta.block.css meta.block.css meta.block.css - meta.sepector */ -/* ^^^^^^ meta.property-list.css meta.block.css meta.at-rule.container.css meta.property-list.css meta.block.css - meta.selector */ +/* ^^^^^^ meta.property-list.css meta.block.css meta.at-rule.container.css meta.property-list.css meta.block.css meta.selector.css */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.container.css meta.property-list.css meta.block.css meta.property-list.css meta.block.css */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.container.css meta.property-list.css meta.block.css - meta.selector */ /* ^^^^^^^ meta.property-list.css meta.block.css meta.at-rule.container.css meta.property-list.css meta.block.css meta.selector.css */ @@ -731,7 +731,7 @@ /* ^^^^^^^^^^ keyword.control.directive.css */ /* ^^^^ entity.other.container.css */ /* ^ punctuation.section.block.begin.css */ -/* ^^^^^ support.type.property-name.css - entity.name.tag */ +/* ^^^^^ entity.name.tag.html.css */ /* ^ punctuation.section.block.begin.css */ /* ^ punctuation.section.block.end.css */ /* ^ punctuation.terminator.rule.css */ @@ -975,7 +975,7 @@ /* ^^^^^^^^^^^^^^^^^ meta.property-list.css meta.block.css meta.at-rule.media.css meta.group.css */ /* ^ meta.property-list.css meta.block.css meta.at-rule.media.css - meta.group - meta.block meta.block */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.media.css meta.block.css - meta.block.css meta.block.css meta.block.css - meta.sepector */ -/* ^^^^^^ meta.property-list.css meta.block.css meta.at-rule.media.css meta.property-list.css meta.block.css - meta.selector */ +/* ^^^^^^ meta.property-list.css meta.block.css meta.at-rule.media.css meta.property-list.css meta.block.css meta.selector.css */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.media.css meta.property-list.css meta.block.css meta.property-list.css meta.block.css */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.media.css meta.property-list.css meta.block.css - meta.selector */ /* ^^^^^^^ meta.property-list.css meta.block.css meta.at-rule.media.css meta.property-list.css meta.block.css meta.selector.css */ @@ -993,7 +993,7 @@ /* ^^^^^^ meta.number.integer.decimal.css */ /* ^ punctuation.section.group.end.css */ /* ^ punctuation.section.block.begin.css */ -/* ^^^^^ support.type.property-name.css - entity.name.tag */ +/* ^^^^^ entity.name.tag.html.css */ /* ^ punctuation.section.block.begin.css */ /* ^ punctuation.section.block.end.css */ /* ^ punctuation.terminator.rule.css */ @@ -1434,10 +1434,13 @@ /* ^^^^^^^^^^^ meta.at-rule.layer.css meta.block.css meta.at-rule.layer.css meta.block.css meta.property-list.css meta.block.css meta.at-rule.layer.css */ /* ^^ meta.at-rule.layer.css meta.block.css meta.at-rule.layer.css meta.block.css meta.property-list.css meta.block.css meta.at-rule.layer.css meta.property-list.css meta.block.css */ table {} -/* ^^^^^ - entity.name.tag */ +/* ^^^^^^ meta.selector.css */ +/* ^^^^^ entity.name.tag.html.css */ > table {} /* ^^^^^^^^ meta.selector.css */ +/* ^ keyword.operator.combinator.css */ +/* ^^^^^ entity.name.tag.html.css */ font: inherit; /* ^^^^ meta.property-name.css support.type.property-name.css */ @@ -1781,7 +1784,7 @@ /* ^^ meta.property-list.css meta.block.css - meta.at-rule */ /* ^^^^^^^^^^ meta.property-list.css meta.block.css meta.at-rule.supports.css - meta.group - meta.block meta.block */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.supports.css meta.block.css - meta.block.css meta.block.css meta.block.css - meta.sepector */ -/* ^^^^^^ meta.property-list.css meta.block.css meta.at-rule.supports.css meta.property-list.css meta.block.css - meta.selector */ +/* ^^^^^^ meta.property-list.css meta.block.css meta.at-rule.supports.css meta.property-list.css meta.block.css meta.selector.css */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.supports.css meta.property-list.css meta.block.css meta.property-list.css meta.block.css */ /* ^^ meta.property-list.css meta.block.css meta.at-rule.supports.css meta.property-list.css meta.block.css - meta.selector */ /* ^^^^^^^ meta.property-list.css meta.block.css meta.at-rule.supports.css meta.property-list.css meta.block.css meta.selector.css */ @@ -1794,7 +1797,7 @@ /* ^ - meta.property-list - meta.block */ /* ^^^^^^^^^ keyword.control.directive.css */ /* ^ punctuation.section.block.begin.css */ -/* ^^^^^ support.type.property-name.css - entity.name.tag */ +/* ^^^^^ entity.name.tag.html.css */ /* ^ punctuation.section.block.begin.css */ /* ^ punctuation.section.block.end.css */ /* ^ punctuation.terminator.rule.css */ @@ -2814,7 +2817,7 @@ /* ^^ meta.property-list.css meta.block.css - meta.property-list meta.property-list - meta.block meta.block */ /* ^ - meta.property-list */ /* ^ punctuation.section.block.begin.css */ -/* ^^^^^ meta.property-name.css support.type.property-name.css */ +/* ^^^^^ meta.selector.css entity.name.tag.other.css */ /* ^ punctuation.section.block.begin.css */ /* ^ punctuation.terminator.rule.css */ /* ^^^^^ support.type.property-name.css */ @@ -2830,7 +2833,7 @@ /* ^^^^^^^^^^^^^^^ meta.property-list.css meta.block.css - meta.property-list meta.property-list - meta.block meta.block */ /* ^ - meta.property-list */ /* ^ punctuation.section.block.begin.css */ -/* ^^^^^ meta.property-name.css support.type.property-name.css */ +/* ^^^^^ meta.selector.css entity.name.tag.other.css */ /* ^ punctuation.section.block.begin.css */ /* ^ punctuation.terminator.rule.css */ /* ^^^^^ support.type.property-name.css */ @@ -4348,17 +4351,19 @@ img{ /* ^ variable.language.parent.css */ /* ^^^^^^^ entity.name.tag.html.css */ article { ... } -/* ^^^^^^^^ meta.property-list.css meta.block.css - meta.selector */ +/* ^^^^^^^^ meta.property-list.css meta.block.css meta.selector.css */ +/* ^^^^^^^ entity.name.tag.html.css */ } .foo:bar > tr.baz[test], div p { /* <- meta.selector.css entity.other.attribute-name.class.css punctuation.definition.entity.css */ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.selector.css */ foo:bar { -/* ^^^ meta.property-list.css meta.block.css meta.property-name.css support.type.property-name.css */ -/* ^ meta.property-list.css meta.block.css punctuation.separator.key-value.css*/ -/* ^^^ meta.property-list.css meta.block.css meta.property-value.css support.constant.property-value.css*/ -/* ^^ meta.property-list.css meta.block.css meta.property-list.css meta.block.css */ +/* ^^^^^^^^ meta.property-list.css meta.block.css meta.selector.css */ +/* ^^^ entity.name.tag.other.css */ +/* ^ punctuation.definition.pseudo-class.css */ +/* ^^^ entity.other.pseudo-class.css */ +/* ^^ meta.property-list.css meta.block.css meta.property-list.css meta.block.css - meta.selector*/ /* ^ punctuation.section.block.begin.css */ foo:bar; /* ^^^^^^^^^^ meta.property-list.css meta.block.css meta.property-list.css meta.block.css */