feat(core): support CSS cascade layers (@layer) - #11462
Open
aleclarson wants to merge 2 commits into
Open
aleclarson wants to merge 2 commits into
aleclarson wants to merge 2 commits into
Conversation
Rules inside @layer blocks were silently dropped by _populateRules, which only descends into @media. This makes NativeScript unable to consume stylesheets emitted by modern build-time CSS compilers (Tailwind v4, Panda, Bamboo — all emit cascade layers). - css-tree adapter captures the @layer prelude and nested rules - _populateRules assigns each ruleset a layerPath of first-seen ordinals; statement form `@layer a, b;` pre-declares order, dotted names resolve through ancestors, anonymous blocks get synthetic ids - compareSelectors orders by layerPath before specificity, with unlayered rules sorting last (winning) per spec - @import "x.css" layer(name) nests the imported sheet's rules
|
View your CI Pipeline Execution ↗ for commit 4182f37
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
commit: |
The build-time css→AST serialization (webpack css2json-loader, vite's
bundled-css serializer in @nativescript/vite helpers/main-entry) runs the
rework parser, which mis-parsed `@layer` into garbage selectors and
dropped the rules. Teach it both forms — `@layer name { rules }` and the
order-declaring `@layer a, b;` statement — emitting layer nodes the
cascade now consumes. Also fixes the legacy __CSS_PARSER__=rework
runtime path.
Spec drives the same ordering through the rework AST end to end.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Checklist
What is the current behavior?
Rules inside
@layerblocks are silently dropped:_populateRules(ui/styling/style-scope.ts) only descends into@mediaat-rules, so every modern build-time CSS pipeline that emits cascade layers (Tailwind v4, Panda CSS, Bamboo, UnoCSS) produces a stylesheet that is dead on NativeScript — see NativeScript/tailwind#197 for the same wall hit from the Tailwind side.What is the new behavior?
@layerapplies per CSS Cascading and Inheritance Level 5:css/css-tree-parser.ts(default__CSS_PARSER__) —@layernodes keep their prelude (layername list) alongside nested rules; the statement form (@layer a, b;) parses with no block.css/lib/parse(vendored rework parser) — same support, which also fixes the legacy__CSS_PARSER__=reworkruntime path and gives the bundler-side serializers a layer-aware parser to converge on.ui/styling/style-scope.ts): a name→ordinal registry shared across all stylesheets feeding the cascade (document-wide, per spec). Statement form pre-declares order; block form registers on first sight; dotted names (a.b) walk ancestors so a top-level@layer a.brefers to the same layer as@layer a { @layer b { … } }; anonymous blocks get synthesized names that can't be re-referenced.ui/styling/css-selector.ts): eachRuleSetcarrieslayerPath: number[];compareSelectorscompares layer paths before specificity. Unlayered rules carry an infinite rank at every depth, so they always beat layered rules — matching the spec, which also handles nested-layer comparison lexicographically.@import "x.css" layer(name)(and barelayerfor anonymous) nests the imported sheet under that layer.Deliberately not implemented:
!importantlayer-order reversal — NativeScript does not implement!importantat all today (cleanupImportantFlagswarns and strips), so there is nothing to reverse.@supports/@container/@scoperemain dropped (they need real condition evaluation; dropping is safer than unconditional application).Known follow-up (out of scope here)
The bundler-side serializers —
@nativescript/vite's bundled-css path (helpers/main-entry.ts,parseCssToAst) and webpack'scss2json-loader— run the npmcsspackage (reworkcss/css), which misparses@layerinto bogus selectors and drops the rules. That package is a separate upstream; swapping those call sites to core's now-layer-aware vendored parser (orcss-tree) is the natural follow-up.Tests
New
ui/styling/css-layer.spec.ts— 13 cases covering population, statement ordering over specificity+position, unlayered-beats-layered, nested/dotted equivalence, anonymous ordering, media queries inside layers, keyframes inside layers, and the same ordering driven through the rework-parser AST end to end. Verified on-device (iOS sim) via a harness probe: a class rule in the later layer beat an id selector in the earlier one, and an unlayered rule beat a layered id selector. Fullpackages/coresuite: 510 tests passing locally.Implements #11461.