@jesscss/core 2.0.0-alpha.4 → 2.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.cjs +20159 -0
- package/lib/index.d.cts +5993 -0
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.ts +5992 -21
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +19926 -22
- package/lib/index.js.map +1 -1
- package/package.json +15 -14
- package/src/__tests__/define-function-record.test.ts +58 -0
- package/src/__tests__/define-function-simple.test.ts +55 -0
- package/src/__tests__/define-function-split-sequence.test.ts +547 -0
- package/src/__tests__/define-function-type-parity.test.ts +9 -0
- package/src/__tests__/define-function.test.ts +763 -0
- package/src/__tests__/num-operations.test.ts +91 -0
- package/src/__tests__/safe-parse.test.ts +374 -0
- package/src/context.ts +896 -0
- package/src/conversions.ts +282 -0
- package/src/debug-log.ts +29 -0
- package/src/define-function.ts +1006 -0
- package/src/deprecation.ts +67 -0
- package/src/globals.d.ts +26 -0
- package/src/index.ts +31 -0
- package/src/jess-error.ts +773 -0
- package/src/logger/deprecation-processing.ts +109 -0
- package/src/logger.ts +31 -0
- package/src/plugin.ts +292 -0
- package/src/tree/LOOKUP_CHAINS.md +35 -0
- package/src/tree/README.md +18 -0
- package/src/tree/__tests__/__snapshots__/extend-eval-integration.test.ts.snap +1455 -0
- package/src/tree/__tests__/ampersand.test.ts +382 -0
- package/src/tree/__tests__/at-rule.test.ts +2047 -0
- package/src/tree/__tests__/basic-render.test.ts +212 -0
- package/src/tree/__tests__/block.test.ts +40 -0
- package/src/tree/__tests__/call.test.ts +346 -0
- package/src/tree/__tests__/color.test.ts +537 -0
- package/src/tree/__tests__/condition.test.ts +186 -0
- package/src/tree/__tests__/control.test.ts +564 -0
- package/src/tree/__tests__/declaration.test.ts +253 -0
- package/src/tree/__tests__/dependency-graph.test.ts +177 -0
- package/src/tree/__tests__/detached-rulesets.test.ts +213 -0
- package/src/tree/__tests__/dimension.test.ts +236 -0
- package/src/tree/__tests__/expression.test.ts +73 -0
- package/src/tree/__tests__/ext-node.test.ts +31 -0
- package/src/tree/__tests__/extend-eval-integration.test.ts +1033 -0
- package/src/tree/__tests__/extend-import-style.test.ts +929 -0
- package/src/tree/__tests__/extend-less-fixtures.test.ts +851 -0
- package/src/tree/__tests__/extend-list.test.ts +31 -0
- package/src/tree/__tests__/extend-roots.test.ts +1045 -0
- package/src/tree/__tests__/extend-rules.test.ts +740 -0
- package/src/tree/__tests__/func.test.ts +171 -0
- package/src/tree/__tests__/import-js.test.ts +33 -0
- package/src/tree/__tests__/import-style-test-helpers.ts +56 -0
- package/src/tree/__tests__/import-style.test.ts +1967 -0
- package/src/tree/__tests__/interpolated-reference.test.ts +44 -0
- package/src/tree/__tests__/interpolated.test.ts +41 -0
- package/src/tree/__tests__/list.test.ts +177 -0
- package/src/tree/__tests__/log.test.ts +83 -0
- package/src/tree/__tests__/mixin-recursion.test.ts +639 -0
- package/src/tree/__tests__/mixin.test.ts +2171 -0
- package/src/tree/__tests__/negative.test.ts +45 -0
- package/src/tree/__tests__/nesting-collapse.test.ts +519 -0
- package/src/tree/__tests__/node-flags-perf.test.ts +195 -0
- package/src/tree/__tests__/node-flags.test.ts +410 -0
- package/src/tree/__tests__/node-graph.test.ts +598 -0
- package/src/tree/__tests__/node-mutation.test.ts +182 -0
- package/src/tree/__tests__/operation.test.ts +18 -0
- package/src/tree/__tests__/paren.test.ts +90 -0
- package/src/tree/__tests__/preserve-mode-output.test.ts +50 -0
- package/src/tree/__tests__/quoted.test.ts +72 -0
- package/src/tree/__tests__/range.test.ts +59 -0
- package/src/tree/__tests__/reference.test.ts +743 -0
- package/src/tree/__tests__/rest.test.ts +29 -0
- package/src/tree/__tests__/rules-raw.test.ts +14 -0
- package/src/tree/__tests__/rules.test.ts +1271 -0
- package/src/tree/__tests__/ruleset.test.ts +597 -0
- package/src/tree/__tests__/selector-attr.test.ts +50 -0
- package/src/tree/__tests__/selector-basic.test.ts +44 -0
- package/src/tree/__tests__/selector-capture.test.ts +22 -0
- package/src/tree/__tests__/selector-complex.test.ts +120 -0
- package/src/tree/__tests__/selector-compound.test.ts +74 -0
- package/src/tree/__tests__/selector-interpolated.test.ts +50 -0
- package/src/tree/__tests__/selector-list.test.ts +59 -0
- package/src/tree/__tests__/selector-pseudo.test.ts +23 -0
- package/src/tree/__tests__/selector.test.ts +182 -0
- package/src/tree/__tests__/sequence.test.ts +226 -0
- package/src/tree/__tests__/serialize-types.test.ts +529 -0
- package/src/tree/__tests__/spaced.test.ts +8 -0
- package/src/tree/__tests__/url.test.ts +72 -0
- package/src/tree/__tests__/var-declaration.test.ts +90 -0
- package/src/tree/ampersand.ts +538 -0
- package/src/tree/any.ts +169 -0
- package/src/tree/at-rule.ts +760 -0
- package/src/tree/block.ts +72 -0
- package/src/tree/bool.ts +46 -0
- package/src/tree/call.ts +593 -0
- package/src/tree/collection.ts +52 -0
- package/src/tree/color.ts +629 -0
- package/src/tree/combinator.ts +30 -0
- package/src/tree/comment.ts +36 -0
- package/src/tree/condition.ts +194 -0
- package/src/tree/control.ts +452 -0
- package/src/tree/declaration-custom.ts +56 -0
- package/src/tree/declaration-var.ts +87 -0
- package/src/tree/declaration.ts +742 -0
- package/src/tree/default-guard.ts +35 -0
- package/src/tree/dimension.ts +392 -0
- package/src/tree/expression.ts +97 -0
- package/src/tree/extend-list.ts +51 -0
- package/src/tree/extend.ts +391 -0
- package/src/tree/function.ts +254 -0
- package/src/tree/import-js.ts +130 -0
- package/src/tree/import-style.ts +875 -0
- package/{lib/tree/index.js → src/tree/index.ts} +49 -22
- package/src/tree/interpolated.ts +346 -0
- package/src/tree/js-array.ts +21 -0
- package/src/tree/js-expr.ts +50 -0
- package/src/tree/js-function.ts +31 -0
- package/src/tree/js-object.ts +22 -0
- package/src/tree/list.ts +415 -0
- package/src/tree/log.ts +89 -0
- package/src/tree/mixin.ts +331 -0
- package/src/tree/negative.ts +58 -0
- package/src/tree/nil.ts +57 -0
- package/src/tree/node-base.ts +1716 -0
- package/src/tree/node-type.ts +122 -0
- package/src/tree/node.ts +118 -0
- package/src/tree/number.ts +54 -0
- package/src/tree/operation.ts +187 -0
- package/src/tree/paren.ts +132 -0
- package/src/tree/query-condition.ts +47 -0
- package/src/tree/quoted.ts +119 -0
- package/src/tree/range.ts +101 -0
- package/src/tree/reference.ts +1099 -0
- package/src/tree/rest.ts +55 -0
- package/src/tree/rules-raw.ts +52 -0
- package/src/tree/rules.ts +2896 -0
- package/src/tree/ruleset.ts +1217 -0
- package/src/tree/selector-attr.ts +172 -0
- package/src/tree/selector-basic.ts +75 -0
- package/src/tree/selector-capture.ts +85 -0
- package/src/tree/selector-complex.ts +189 -0
- package/src/tree/selector-compound.ts +205 -0
- package/src/tree/selector-interpolated.ts +95 -0
- package/src/tree/selector-list.ts +245 -0
- package/src/tree/selector-pseudo.ts +173 -0
- package/src/tree/selector-simple.ts +10 -0
- package/src/tree/selector.ts +152 -0
- package/src/tree/sequence.ts +463 -0
- package/src/tree/tree.ts +130 -0
- package/src/tree/url.ts +95 -0
- package/src/tree/util/EXTEND_ARCHITECTURE_ANALYSIS.md +215 -0
- package/src/tree/util/EXTEND_AUDIT.md +233 -0
- package/src/tree/util/EXTEND_BASELINE.md +64 -0
- package/src/tree/util/EXTEND_CALL_GRAPH_ANALYSIS.md +244 -0
- package/src/tree/util/EXTEND_DOCS.md +24 -0
- package/src/tree/util/EXTEND_FINAL_SUMMARY.md +95 -0
- package/src/tree/util/EXTEND_FUNCTION_AUDIT.md +1433 -0
- package/src/tree/util/EXTEND_OPTIMIZATION_PLAN.md +114 -0
- package/src/tree/util/EXTEND_REFACTORING_SUMMARY.md +152 -0
- package/src/tree/util/EXTEND_RULES.md +74 -0
- package/src/tree/util/EXTEND_UNUSED_FUNCTIONS.md +127 -0
- package/src/tree/util/EXTEND_UNUSED_FUNCTIONS_ANALYSIS.md +227 -0
- package/src/tree/util/NODE_COPY_REDUCTION_PLAN.md +12 -0
- package/src/tree/util/__tests__/EXTEND_TEST_INDEX.md +59 -0
- package/src/tree/util/__tests__/OPTIMIZATION-ANALYSIS.md +130 -0
- package/src/tree/util/__tests__/WALK_AND_CONSUME_DESIGN.md +138 -0
- package/src/tree/util/__tests__/_archive/2026-02-09__OPTIMIZATION-ANALYSIS.md +9 -0
- package/src/tree/util/__tests__/_archive/README.md +4 -0
- package/src/tree/util/__tests__/bitset.test.ts +142 -0
- package/src/tree/util/__tests__/debug-log.ts +50 -0
- package/src/tree/util/__tests__/extend-comment-handling.test.ts +187 -0
- package/src/tree/util/__tests__/extend-core-unit.test.ts +941 -0
- package/src/tree/util/__tests__/extend-pipeline-bench.test.ts +154 -0
- package/src/tree/util/__tests__/extend-pipeline-bench.ts +190 -0
- package/src/tree/util/__tests__/fast-reject.test.ts +377 -0
- package/src/tree/util/__tests__/is-node.test.ts +63 -0
- package/src/tree/util/__tests__/list-like.test.ts +63 -0
- package/src/tree/util/__tests__/outputwriter.test.ts +523 -0
- package/src/tree/util/__tests__/print.test.ts +183 -0
- package/src/tree/util/__tests__/process-extends.test.ts +226 -0
- package/src/tree/util/__tests__/process-leading-is.test.ts +205 -0
- package/src/tree/util/__tests__/recursion-helper.test.ts +184 -0
- package/src/tree/util/__tests__/selector-match-unit.test.ts +1427 -0
- package/src/tree/util/__tests__/sourcemap.test.ts +117 -0
- package/src/tree/util/ampersand-template.ts +9 -0
- package/src/tree/util/bitset.ts +194 -0
- package/src/tree/util/calculate.ts +11 -0
- package/src/tree/util/cast.ts +89 -0
- package/src/tree/util/cloning.ts +8 -0
- package/src/tree/util/collections.ts +299 -0
- package/src/tree/util/compare.ts +90 -0
- package/src/tree/util/cursor.ts +171 -0
- package/src/tree/util/extend-core.ts +2139 -0
- package/src/tree/util/extend-roots.ts +1108 -0
- package/src/tree/util/field-helpers.ts +354 -0
- package/src/tree/util/is-node.ts +43 -0
- package/src/tree/util/list-like.ts +93 -0
- package/src/tree/util/mixin-instance-primitives.ts +2020 -0
- package/src/tree/util/print.ts +303 -0
- package/src/tree/util/process-leading-is.ts +421 -0
- package/src/tree/util/recursion-helper.ts +54 -0
- package/src/tree/util/regex.ts +2 -0
- package/src/tree/util/registry-utils.ts +1953 -0
- package/src/tree/util/ruleset-trace.ts +17 -0
- package/src/tree/util/scoped-body-eval.ts +320 -0
- package/src/tree/util/selector-match-core.ts +2005 -0
- package/src/tree/util/selector-utils.ts +757 -0
- package/src/tree/util/serialize-helper.ts +535 -0
- package/src/tree/util/serialize-types.ts +318 -0
- package/src/tree/util/should-operate.ts +78 -0
- package/src/tree/util/sourcemap.ts +37 -0
- package/src/types/config.ts +247 -0
- package/src/types/index.ts +12 -0
- package/{lib/types/modes.d.ts → src/types/modes.ts} +2 -1
- package/src/types.d.ts +9 -0
- package/src/types.ts +68 -0
- package/src/use-webpack-resolver.ts +56 -0
- package/src/visitor/__tests__/visitor.test.ts +136 -0
- package/src/visitor/index.ts +263 -0
- package/{lib/visitor/less-visitor.js → src/visitor/less-visitor.ts} +3 -2
- package/lib/context.d.ts +0 -352
- package/lib/context.d.ts.map +0 -1
- package/lib/context.js +0 -636
- package/lib/context.js.map +0 -1
- package/lib/conversions.d.ts +0 -73
- package/lib/conversions.d.ts.map +0 -1
- package/lib/conversions.js +0 -253
- package/lib/conversions.js.map +0 -1
- package/lib/debug-log.d.ts +0 -2
- package/lib/debug-log.d.ts.map +0 -1
- package/lib/debug-log.js +0 -27
- package/lib/debug-log.js.map +0 -1
- package/lib/define-function.d.ts +0 -587
- package/lib/define-function.d.ts.map +0 -1
- package/lib/define-function.js +0 -726
- package/lib/define-function.js.map +0 -1
- package/lib/deprecation.d.ts +0 -34
- package/lib/deprecation.d.ts.map +0 -1
- package/lib/deprecation.js +0 -57
- package/lib/deprecation.js.map +0 -1
- package/lib/jess-error.d.ts +0 -343
- package/lib/jess-error.d.ts.map +0 -1
- package/lib/jess-error.js +0 -508
- package/lib/jess-error.js.map +0 -1
- package/lib/logger/deprecation-processing.d.ts +0 -41
- package/lib/logger/deprecation-processing.d.ts.map +0 -1
- package/lib/logger/deprecation-processing.js +0 -81
- package/lib/logger/deprecation-processing.js.map +0 -1
- package/lib/logger.d.ts +0 -10
- package/lib/logger.d.ts.map +0 -1
- package/lib/logger.js +0 -20
- package/lib/logger.js.map +0 -1
- package/lib/plugin.d.ts +0 -94
- package/lib/plugin.d.ts.map +0 -1
- package/lib/plugin.js +0 -174
- package/lib/plugin.js.map +0 -1
- package/lib/tree/ampersand.d.ts +0 -94
- package/lib/tree/ampersand.d.ts.map +0 -1
- package/lib/tree/ampersand.js +0 -269
- package/lib/tree/ampersand.js.map +0 -1
- package/lib/tree/any.d.ts +0 -58
- package/lib/tree/any.d.ts.map +0 -1
- package/lib/tree/any.js +0 -104
- package/lib/tree/any.js.map +0 -1
- package/lib/tree/at-rule.d.ts +0 -53
- package/lib/tree/at-rule.d.ts.map +0 -1
- package/lib/tree/at-rule.js +0 -503
- package/lib/tree/at-rule.js.map +0 -1
- package/lib/tree/block.d.ts +0 -22
- package/lib/tree/block.d.ts.map +0 -1
- package/lib/tree/block.js +0 -24
- package/lib/tree/block.js.map +0 -1
- package/lib/tree/bool.d.ts +0 -18
- package/lib/tree/bool.d.ts.map +0 -1
- package/lib/tree/bool.js +0 -28
- package/lib/tree/bool.js.map +0 -1
- package/lib/tree/call.d.ts +0 -66
- package/lib/tree/call.d.ts.map +0 -1
- package/lib/tree/call.js +0 -306
- package/lib/tree/call.js.map +0 -1
- package/lib/tree/collection.d.ts +0 -30
- package/lib/tree/collection.d.ts.map +0 -1
- package/lib/tree/collection.js +0 -37
- package/lib/tree/collection.js.map +0 -1
- package/lib/tree/color.d.ts +0 -101
- package/lib/tree/color.d.ts.map +0 -1
- package/lib/tree/color.js +0 -513
- package/lib/tree/color.js.map +0 -1
- package/lib/tree/combinator.d.ts +0 -13
- package/lib/tree/combinator.d.ts.map +0 -1
- package/lib/tree/combinator.js +0 -12
- package/lib/tree/combinator.js.map +0 -1
- package/lib/tree/comment.d.ts +0 -20
- package/lib/tree/comment.d.ts.map +0 -1
- package/lib/tree/comment.js +0 -19
- package/lib/tree/comment.js.map +0 -1
- package/lib/tree/condition.d.ts +0 -31
- package/lib/tree/condition.d.ts.map +0 -1
- package/lib/tree/condition.js +0 -103
- package/lib/tree/condition.js.map +0 -1
- package/lib/tree/control.d.ts +0 -104
- package/lib/tree/control.d.ts.map +0 -1
- package/lib/tree/control.js +0 -430
- package/lib/tree/control.js.map +0 -1
- package/lib/tree/declaration-custom.d.ts +0 -18
- package/lib/tree/declaration-custom.d.ts.map +0 -1
- package/lib/tree/declaration-custom.js +0 -24
- package/lib/tree/declaration-custom.js.map +0 -1
- package/lib/tree/declaration-var.d.ts +0 -35
- package/lib/tree/declaration-var.d.ts.map +0 -1
- package/lib/tree/declaration-var.js +0 -63
- package/lib/tree/declaration-var.js.map +0 -1
- package/lib/tree/declaration.d.ts +0 -78
- package/lib/tree/declaration.d.ts.map +0 -1
- package/lib/tree/declaration.js +0 -286
- package/lib/tree/declaration.js.map +0 -1
- package/lib/tree/default-guard.d.ts +0 -15
- package/lib/tree/default-guard.d.ts.map +0 -1
- package/lib/tree/default-guard.js +0 -19
- package/lib/tree/default-guard.js.map +0 -1
- package/lib/tree/dimension.d.ts +0 -34
- package/lib/tree/dimension.d.ts.map +0 -1
- package/lib/tree/dimension.js +0 -294
- package/lib/tree/dimension.js.map +0 -1
- package/lib/tree/expression.d.ts +0 -25
- package/lib/tree/expression.d.ts.map +0 -1
- package/lib/tree/expression.js +0 -32
- package/lib/tree/expression.js.map +0 -1
- package/lib/tree/extend-list.d.ts +0 -23
- package/lib/tree/extend-list.d.ts.map +0 -1
- package/lib/tree/extend-list.js +0 -23
- package/lib/tree/extend-list.js.map +0 -1
- package/lib/tree/extend.d.ts +0 -47
- package/lib/tree/extend.d.ts.map +0 -1
- package/lib/tree/extend.js +0 -296
- package/lib/tree/extend.js.map +0 -1
- package/lib/tree/function.d.ts +0 -48
- package/lib/tree/function.d.ts.map +0 -1
- package/lib/tree/function.js +0 -74
- package/lib/tree/function.js.map +0 -1
- package/lib/tree/import-js.d.ts +0 -35
- package/lib/tree/import-js.d.ts.map +0 -1
- package/lib/tree/import-js.js +0 -45
- package/lib/tree/import-js.js.map +0 -1
- package/lib/tree/import-style.d.ts +0 -156
- package/lib/tree/import-style.d.ts.map +0 -1
- package/lib/tree/import-style.js +0 -566
- package/lib/tree/import-style.js.map +0 -1
- package/lib/tree/index.d.ts +0 -71
- package/lib/tree/index.d.ts.map +0 -1
- package/lib/tree/index.js.map +0 -1
- package/lib/tree/interpolated-reference.d.ts +0 -24
- package/lib/tree/interpolated-reference.d.ts.map +0 -1
- package/lib/tree/interpolated-reference.js +0 -37
- package/lib/tree/interpolated-reference.js.map +0 -1
- package/lib/tree/interpolated.d.ts +0 -62
- package/lib/tree/interpolated.d.ts.map +0 -1
- package/lib/tree/interpolated.js +0 -204
- package/lib/tree/interpolated.js.map +0 -1
- package/lib/tree/js-array.d.ts +0 -10
- package/lib/tree/js-array.d.ts.map +0 -1
- package/lib/tree/js-array.js +0 -10
- package/lib/tree/js-array.js.map +0 -1
- package/lib/tree/js-expr.d.ts +0 -23
- package/lib/tree/js-expr.d.ts.map +0 -1
- package/lib/tree/js-expr.js +0 -28
- package/lib/tree/js-expr.js.map +0 -1
- package/lib/tree/js-function.d.ts +0 -20
- package/lib/tree/js-function.d.ts.map +0 -1
- package/lib/tree/js-function.js +0 -16
- package/lib/tree/js-function.js.map +0 -1
- package/lib/tree/js-object.d.ts +0 -10
- package/lib/tree/js-object.d.ts.map +0 -1
- package/lib/tree/js-object.js +0 -10
- package/lib/tree/js-object.js.map +0 -1
- package/lib/tree/list.d.ts +0 -38
- package/lib/tree/list.d.ts.map +0 -1
- package/lib/tree/list.js +0 -83
- package/lib/tree/list.js.map +0 -1
- package/lib/tree/log.d.ts +0 -29
- package/lib/tree/log.d.ts.map +0 -1
- package/lib/tree/log.js +0 -56
- package/lib/tree/log.js.map +0 -1
- package/lib/tree/mixin.d.ts +0 -87
- package/lib/tree/mixin.d.ts.map +0 -1
- package/lib/tree/mixin.js +0 -112
- package/lib/tree/mixin.js.map +0 -1
- package/lib/tree/negative.d.ts +0 -17
- package/lib/tree/negative.d.ts.map +0 -1
- package/lib/tree/negative.js +0 -22
- package/lib/tree/negative.js.map +0 -1
- package/lib/tree/nil.d.ts +0 -30
- package/lib/tree/nil.d.ts.map +0 -1
- package/lib/tree/nil.js +0 -35
- package/lib/tree/nil.js.map +0 -1
- package/lib/tree/node-base.d.ts +0 -361
- package/lib/tree/node-base.d.ts.map +0 -1
- package/lib/tree/node-base.js +0 -930
- package/lib/tree/node-base.js.map +0 -1
- package/lib/tree/node.d.ts +0 -10
- package/lib/tree/node.d.ts.map +0 -1
- package/lib/tree/node.js +0 -45
- package/lib/tree/node.js.map +0 -1
- package/lib/tree/number.d.ts +0 -21
- package/lib/tree/number.d.ts.map +0 -1
- package/lib/tree/number.js +0 -27
- package/lib/tree/number.js.map +0 -1
- package/lib/tree/operation.d.ts +0 -26
- package/lib/tree/operation.d.ts.map +0 -1
- package/lib/tree/operation.js +0 -103
- package/lib/tree/operation.js.map +0 -1
- package/lib/tree/paren.d.ts +0 -19
- package/lib/tree/paren.d.ts.map +0 -1
- package/lib/tree/paren.js +0 -92
- package/lib/tree/paren.js.map +0 -1
- package/lib/tree/query-condition.d.ts +0 -17
- package/lib/tree/query-condition.d.ts.map +0 -1
- package/lib/tree/query-condition.js +0 -39
- package/lib/tree/query-condition.js.map +0 -1
- package/lib/tree/quoted.d.ts +0 -28
- package/lib/tree/quoted.d.ts.map +0 -1
- package/lib/tree/quoted.js +0 -75
- package/lib/tree/quoted.js.map +0 -1
- package/lib/tree/range.d.ts +0 -33
- package/lib/tree/range.d.ts.map +0 -1
- package/lib/tree/range.js +0 -47
- package/lib/tree/range.js.map +0 -1
- package/lib/tree/reference.d.ts +0 -76
- package/lib/tree/reference.d.ts.map +0 -1
- package/lib/tree/reference.js +0 -521
- package/lib/tree/reference.js.map +0 -1
- package/lib/tree/rest.d.ts +0 -15
- package/lib/tree/rest.d.ts.map +0 -1
- package/lib/tree/rest.js +0 -32
- package/lib/tree/rest.js.map +0 -1
- package/lib/tree/rules-raw.d.ts +0 -17
- package/lib/tree/rules-raw.d.ts.map +0 -1
- package/lib/tree/rules-raw.js +0 -37
- package/lib/tree/rules-raw.js.map +0 -1
- package/lib/tree/rules.d.ts +0 -262
- package/lib/tree/rules.d.ts.map +0 -1
- package/lib/tree/rules.js +0 -2359
- package/lib/tree/rules.js.map +0 -1
- package/lib/tree/ruleset.d.ts +0 -92
- package/lib/tree/ruleset.d.ts.map +0 -1
- package/lib/tree/ruleset.js +0 -528
- package/lib/tree/ruleset.js.map +0 -1
- package/lib/tree/selector-attr.d.ts +0 -31
- package/lib/tree/selector-attr.d.ts.map +0 -1
- package/lib/tree/selector-attr.js +0 -99
- package/lib/tree/selector-attr.js.map +0 -1
- package/lib/tree/selector-basic.d.ts +0 -24
- package/lib/tree/selector-basic.d.ts.map +0 -1
- package/lib/tree/selector-basic.js +0 -38
- package/lib/tree/selector-basic.js.map +0 -1
- package/lib/tree/selector-capture.d.ts +0 -23
- package/lib/tree/selector-capture.d.ts.map +0 -1
- package/lib/tree/selector-capture.js +0 -34
- package/lib/tree/selector-capture.js.map +0 -1
- package/lib/tree/selector-complex.d.ts +0 -40
- package/lib/tree/selector-complex.d.ts.map +0 -1
- package/lib/tree/selector-complex.js +0 -143
- package/lib/tree/selector-complex.js.map +0 -1
- package/lib/tree/selector-compound.d.ts +0 -16
- package/lib/tree/selector-compound.d.ts.map +0 -1
- package/lib/tree/selector-compound.js +0 -114
- package/lib/tree/selector-compound.js.map +0 -1
- package/lib/tree/selector-interpolated.d.ts +0 -23
- package/lib/tree/selector-interpolated.d.ts.map +0 -1
- package/lib/tree/selector-interpolated.js +0 -27
- package/lib/tree/selector-interpolated.js.map +0 -1
- package/lib/tree/selector-list.d.ts +0 -17
- package/lib/tree/selector-list.d.ts.map +0 -1
- package/lib/tree/selector-list.js +0 -174
- package/lib/tree/selector-list.js.map +0 -1
- package/lib/tree/selector-pseudo.d.ts +0 -42
- package/lib/tree/selector-pseudo.d.ts.map +0 -1
- package/lib/tree/selector-pseudo.js +0 -204
- package/lib/tree/selector-pseudo.js.map +0 -1
- package/lib/tree/selector-simple.d.ts +0 -5
- package/lib/tree/selector-simple.d.ts.map +0 -1
- package/lib/tree/selector-simple.js +0 -6
- package/lib/tree/selector-simple.js.map +0 -1
- package/lib/tree/selector.d.ts +0 -43
- package/lib/tree/selector.d.ts.map +0 -1
- package/lib/tree/selector.js +0 -56
- package/lib/tree/selector.js.map +0 -1
- package/lib/tree/sequence.d.ts +0 -43
- package/lib/tree/sequence.d.ts.map +0 -1
- package/lib/tree/sequence.js +0 -151
- package/lib/tree/sequence.js.map +0 -1
- package/lib/tree/tree.d.ts +0 -87
- package/lib/tree/tree.d.ts.map +0 -1
- package/lib/tree/tree.js +0 -2
- package/lib/tree/tree.js.map +0 -1
- package/lib/tree/url.d.ts +0 -18
- package/lib/tree/url.d.ts.map +0 -1
- package/lib/tree/url.js +0 -35
- package/lib/tree/url.js.map +0 -1
- package/lib/tree/util/__tests__/debug-log.d.ts +0 -1
- package/lib/tree/util/__tests__/debug-log.d.ts.map +0 -1
- package/lib/tree/util/__tests__/debug-log.js +0 -36
- package/lib/tree/util/__tests__/debug-log.js.map +0 -1
- package/lib/tree/util/calculate.d.ts +0 -3
- package/lib/tree/util/calculate.d.ts.map +0 -1
- package/lib/tree/util/calculate.js +0 -10
- package/lib/tree/util/calculate.js.map +0 -1
- package/lib/tree/util/cast.d.ts +0 -10
- package/lib/tree/util/cast.d.ts.map +0 -1
- package/lib/tree/util/cast.js +0 -87
- package/lib/tree/util/cast.js.map +0 -1
- package/lib/tree/util/cloning.d.ts +0 -4
- package/lib/tree/util/cloning.d.ts.map +0 -1
- package/lib/tree/util/cloning.js +0 -8
- package/lib/tree/util/cloning.js.map +0 -1
- package/lib/tree/util/collections.d.ts +0 -57
- package/lib/tree/util/collections.d.ts.map +0 -1
- package/lib/tree/util/collections.js +0 -136
- package/lib/tree/util/collections.js.map +0 -1
- package/lib/tree/util/compare.d.ts +0 -11
- package/lib/tree/util/compare.d.ts.map +0 -1
- package/lib/tree/util/compare.js +0 -89
- package/lib/tree/util/compare.js.map +0 -1
- package/lib/tree/util/extend-helpers.d.ts +0 -2
- package/lib/tree/util/extend-helpers.d.ts.map +0 -1
- package/lib/tree/util/extend-helpers.js +0 -2
- package/lib/tree/util/extend-helpers.js.map +0 -1
- package/lib/tree/util/extend-roots.d.ts +0 -37
- package/lib/tree/util/extend-roots.d.ts.map +0 -1
- package/lib/tree/util/extend-roots.js +0 -700
- package/lib/tree/util/extend-roots.js.map +0 -1
- package/lib/tree/util/extend-roots.old.d.ts +0 -132
- package/lib/tree/util/extend-roots.old.d.ts.map +0 -1
- package/lib/tree/util/extend-roots.old.js +0 -2272
- package/lib/tree/util/extend-roots.old.js.map +0 -1
- package/lib/tree/util/extend-trace-debug.d.ts +0 -13
- package/lib/tree/util/extend-trace-debug.d.ts.map +0 -1
- package/lib/tree/util/extend-trace-debug.js +0 -34
- package/lib/tree/util/extend-trace-debug.js.map +0 -1
- package/lib/tree/util/extend-walk.d.ts +0 -53
- package/lib/tree/util/extend-walk.d.ts.map +0 -1
- package/lib/tree/util/extend-walk.js +0 -881
- package/lib/tree/util/extend-walk.js.map +0 -1
- package/lib/tree/util/extend.d.ts +0 -218
- package/lib/tree/util/extend.d.ts.map +0 -1
- package/lib/tree/util/extend.js +0 -3182
- package/lib/tree/util/extend.js.map +0 -1
- package/lib/tree/util/find-extendable-locations.d.ts +0 -2
- package/lib/tree/util/find-extendable-locations.d.ts.map +0 -1
- package/lib/tree/util/find-extendable-locations.js +0 -2
- package/lib/tree/util/find-extendable-locations.js.map +0 -1
- package/lib/tree/util/format.d.ts +0 -20
- package/lib/tree/util/format.d.ts.map +0 -1
- package/lib/tree/util/format.js +0 -67
- package/lib/tree/util/format.js.map +0 -1
- package/lib/tree/util/is-node.d.ts +0 -13
- package/lib/tree/util/is-node.d.ts.map +0 -1
- package/lib/tree/util/is-node.js +0 -43
- package/lib/tree/util/is-node.js.map +0 -1
- package/lib/tree/util/print.d.ts +0 -80
- package/lib/tree/util/print.d.ts.map +0 -1
- package/lib/tree/util/print.js +0 -205
- package/lib/tree/util/print.js.map +0 -1
- package/lib/tree/util/process-leading-is.d.ts +0 -25
- package/lib/tree/util/process-leading-is.d.ts.map +0 -1
- package/lib/tree/util/process-leading-is.js +0 -364
- package/lib/tree/util/process-leading-is.js.map +0 -1
- package/lib/tree/util/recursion-helper.d.ts +0 -15
- package/lib/tree/util/recursion-helper.d.ts.map +0 -1
- package/lib/tree/util/recursion-helper.js +0 -43
- package/lib/tree/util/recursion-helper.js.map +0 -1
- package/lib/tree/util/regex.d.ts +0 -4
- package/lib/tree/util/regex.d.ts.map +0 -1
- package/lib/tree/util/regex.js +0 -4
- package/lib/tree/util/regex.js.map +0 -1
- package/lib/tree/util/registry-utils.d.ts +0 -192
- package/lib/tree/util/registry-utils.d.ts.map +0 -1
- package/lib/tree/util/registry-utils.js +0 -1214
- package/lib/tree/util/registry-utils.js.map +0 -1
- package/lib/tree/util/ruleset-trace.d.ts +0 -4
- package/lib/tree/util/ruleset-trace.d.ts.map +0 -1
- package/lib/tree/util/ruleset-trace.js +0 -14
- package/lib/tree/util/ruleset-trace.js.map +0 -1
- package/lib/tree/util/selector-compare.d.ts +0 -2
- package/lib/tree/util/selector-compare.d.ts.map +0 -1
- package/lib/tree/util/selector-compare.js +0 -2
- package/lib/tree/util/selector-compare.js.map +0 -1
- package/lib/tree/util/selector-match-core.d.ts +0 -184
- package/lib/tree/util/selector-match-core.d.ts.map +0 -1
- package/lib/tree/util/selector-match-core.js +0 -1603
- package/lib/tree/util/selector-match-core.js.map +0 -1
- package/lib/tree/util/selector-utils.d.ts +0 -30
- package/lib/tree/util/selector-utils.d.ts.map +0 -1
- package/lib/tree/util/selector-utils.js +0 -100
- package/lib/tree/util/selector-utils.js.map +0 -1
- package/lib/tree/util/serialize-helper.d.ts +0 -13
- package/lib/tree/util/serialize-helper.d.ts.map +0 -1
- package/lib/tree/util/serialize-helper.js +0 -387
- package/lib/tree/util/serialize-helper.js.map +0 -1
- package/lib/tree/util/serialize-types.d.ts +0 -9
- package/lib/tree/util/serialize-types.d.ts.map +0 -1
- package/lib/tree/util/serialize-types.js +0 -216
- package/lib/tree/util/serialize-types.js.map +0 -1
- package/lib/tree/util/should-operate.d.ts +0 -23
- package/lib/tree/util/should-operate.d.ts.map +0 -1
- package/lib/tree/util/should-operate.js +0 -46
- package/lib/tree/util/should-operate.js.map +0 -1
- package/lib/tree/util/sourcemap.d.ts +0 -7
- package/lib/tree/util/sourcemap.d.ts.map +0 -1
- package/lib/tree/util/sourcemap.js +0 -25
- package/lib/tree/util/sourcemap.js.map +0 -1
- package/lib/types/config.d.ts +0 -205
- package/lib/types/config.d.ts.map +0 -1
- package/lib/types/config.js +0 -2
- package/lib/types/config.js.map +0 -1
- package/lib/types/index.d.ts +0 -15
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/index.js +0 -3
- package/lib/types/index.js.map +0 -1
- package/lib/types/modes.d.ts.map +0 -1
- package/lib/types/modes.js +0 -2
- package/lib/types/modes.js.map +0 -1
- package/lib/types.d.ts +0 -61
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -2
- package/lib/types.js.map +0 -1
- package/lib/use-webpack-resolver.d.ts +0 -9
- package/lib/use-webpack-resolver.d.ts.map +0 -1
- package/lib/use-webpack-resolver.js +0 -41
- package/lib/use-webpack-resolver.js.map +0 -1
- package/lib/visitor/index.d.ts +0 -136
- package/lib/visitor/index.d.ts.map +0 -1
- package/lib/visitor/index.js +0 -135
- package/lib/visitor/index.js.map +0 -1
- package/lib/visitor/less-visitor.d.ts +0 -7
- package/lib/visitor/less-visitor.d.ts.map +0 -1
- package/lib/visitor/less-visitor.js.map +0 -1
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
import { Selector } from '../selector.js';
|
|
2
|
+
import { Combinator } from '../combinator.js';
|
|
3
|
+
import { ComplexSelector } from '../selector-complex.js';
|
|
4
|
+
import { CompoundSelector } from '../selector-compound.js';
|
|
5
|
+
import { SelectorList } from '../selector-list.js';
|
|
6
|
+
import { PseudoSelector } from '../selector-pseudo.js';
|
|
7
|
+
import { BasicSelector } from '../selector-basic.js';
|
|
8
|
+
import { AMPERSAND_TEMPLATE_CONTENTS_REGEX } from './ampersand-template.js';
|
|
9
|
+
import type { Rules } from '../rules.js';
|
|
10
|
+
import type { Ruleset } from '../ruleset.js';
|
|
11
|
+
import type { Node, RenderKey } from '../node.js';
|
|
12
|
+
import { isNode } from './is-node.js';
|
|
13
|
+
import { N } from '../node-type.js';
|
|
14
|
+
import { Nil } from '../nil.js';
|
|
15
|
+
import { F_IMPLICIT_AMPERSAND, F_EXTENDED } from '../node.js';
|
|
16
|
+
import type { Context } from '../../context.js';
|
|
17
|
+
import { getParent } from './field-helpers.js';
|
|
18
|
+
import { getParentEdge } from './cursor.js';
|
|
19
|
+
|
|
20
|
+
const ampersandTemplateInterpolationRegex = /[$@]\{[^}]+\}/g;
|
|
21
|
+
const ampersandTemplateRegex = new RegExp(`^(?:${AMPERSAND_TEMPLATE_CONTENTS_REGEX.source})$`);
|
|
22
|
+
|
|
23
|
+
function getSelectorListArgNode(target: Selector): SelectorList | undefined {
|
|
24
|
+
const arg = Reflect.get(target, 'arg');
|
|
25
|
+
return isNode(arg, N.SelectorList) ? arg : undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getPseudoSelectorNode(node: Selector): PseudoSelector | undefined {
|
|
29
|
+
return isNode(node, N.PseudoSelector) ? node : undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns true when `sel` is purely `&` with no explicit template — meaning the
|
|
34
|
+
* ruleset's selector is an unmodified mirror of its parent. Such rulesets
|
|
35
|
+
* are updated by refreshNestedRulesetSelectors and should not be directly
|
|
36
|
+
* targeted by the extend loop.
|
|
37
|
+
*/
|
|
38
|
+
export function isBareAmpersandOwnSelector(sel: Selector | Nil): boolean {
|
|
39
|
+
if (!sel || sel instanceof Nil) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
if (isNode(sel, N.Ampersand)) {
|
|
43
|
+
return sel.isPlainAmpersand();
|
|
44
|
+
}
|
|
45
|
+
if (isNode(sel, N.CompoundSelector)) {
|
|
46
|
+
const items = sel.get('value');
|
|
47
|
+
return items.length === 1
|
|
48
|
+
&& isNode(items[0], N.Ampersand)
|
|
49
|
+
&& items[0].isPlainAmpersand();
|
|
50
|
+
}
|
|
51
|
+
if (isNode(sel, N.ComplexSelector)) {
|
|
52
|
+
const items = sel.get('value');
|
|
53
|
+
return items.length === 1
|
|
54
|
+
&& isNode(items[0], N.Ampersand)
|
|
55
|
+
&& items[0].isPlainAmpersand();
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Smart `:is()` wrapper. Flattens nested generated `:is()`, deduplicates,
|
|
62
|
+
* and skips wrapping single items.
|
|
63
|
+
*/
|
|
64
|
+
export function wrapInGeneratedIs(selector: Selector): Selector {
|
|
65
|
+
const items: Selector[] = [];
|
|
66
|
+
const seen = new Set<string>();
|
|
67
|
+
|
|
68
|
+
const addItem = (item: Selector): void => {
|
|
69
|
+
let pseudo = getPseudoSelectorNode(item);
|
|
70
|
+
if (pseudo && !(pseudo.generated && pseudo.get('name') === ':is')) {
|
|
71
|
+
pseudo = undefined;
|
|
72
|
+
}
|
|
73
|
+
if (!pseudo) {
|
|
74
|
+
const compound = isNode(item, N.CompoundSelector) ? item : undefined;
|
|
75
|
+
if (compound && compound.get('value').length === 1) {
|
|
76
|
+
const only = compound.get('value')[0];
|
|
77
|
+
pseudo = isNode(only, N.PseudoSelector) ? only : undefined;
|
|
78
|
+
if (!(pseudo && pseudo.generated && pseudo.get('name') === ':is')) {
|
|
79
|
+
pseudo = undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const pseudoArg = pseudo ? getSelectorListArgNode(pseudo) : undefined;
|
|
84
|
+
if (pseudoArg) {
|
|
85
|
+
for (const child of pseudoArg.get('value')) {
|
|
86
|
+
addItem(child);
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const key = item.valueOf();
|
|
91
|
+
if (!seen.has(key)) {
|
|
92
|
+
seen.add(key);
|
|
93
|
+
items.push(item);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
if (isNode(selector, N.SelectorList)) {
|
|
98
|
+
for (const item of selector.get('value')) {
|
|
99
|
+
addItem(item);
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
addItem(selector);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (items.length === 1) {
|
|
106
|
+
return items[0]!;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const list = SelectorList.create(items).inherit(selector);
|
|
110
|
+
list.pre = undefined;
|
|
111
|
+
list.post = undefined;
|
|
112
|
+
const wrapper = PseudoSelector.create({ name: ':is', arg: list });
|
|
113
|
+
wrapper.generated = true;
|
|
114
|
+
return wrapper.inherit(selector);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Walk node.parent → Rules → Ruleset to find the containing Ruleset, if any. */
|
|
118
|
+
export function getCurrentParentNode(node: Node, context?: Context | RenderKey): Node | undefined {
|
|
119
|
+
if (context && typeof context !== 'object') {
|
|
120
|
+
return getParentEdge({ node, renderKey: context })?.node;
|
|
121
|
+
}
|
|
122
|
+
return context ? getParent(node, context) : node.parent;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Walk node.parent → Rules → Ruleset to find the containing Ruleset, if any. */
|
|
126
|
+
export function getParentRuleset(node: Node, context?: Context): Ruleset | undefined {
|
|
127
|
+
const visited = new Set<Node>();
|
|
128
|
+
let current = getCurrentParentNode(node, context);
|
|
129
|
+
|
|
130
|
+
while (current && !visited.has(current)) {
|
|
131
|
+
if (isNode(current, N.Ruleset)) {
|
|
132
|
+
return current;
|
|
133
|
+
}
|
|
134
|
+
visited.add(current);
|
|
135
|
+
current = getCurrentParentNode(current, context);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function hasSourceExtendWrapperParent(node: Node): boolean {
|
|
142
|
+
const parent = node.parent;
|
|
143
|
+
if (!isNode(parent, N.Rules)) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const sourceRules = isNode(parent.sourceNode, N.Rules)
|
|
148
|
+
? parent.sourceNode as Rules
|
|
149
|
+
: parent;
|
|
150
|
+
const sourceChildren = sourceRules.value;
|
|
151
|
+
|
|
152
|
+
let sawExtend = false;
|
|
153
|
+
let sawRuleset = false;
|
|
154
|
+
for (const child of sourceChildren) {
|
|
155
|
+
if (isNode(child, N.Extend)) {
|
|
156
|
+
sawExtend = true;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (isNode(child, N.Ruleset)) {
|
|
160
|
+
sawRuleset = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return sawExtend && sawRuleset;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function flattenSelectorListAlternatives(list: SelectorList): SelectorList {
|
|
168
|
+
const flattened: Selector[] = [];
|
|
169
|
+
const seen = new Set<string>();
|
|
170
|
+
|
|
171
|
+
const pushUnique = (selector: Selector): void => {
|
|
172
|
+
const key = selector.valueOf();
|
|
173
|
+
if (seen.has(key)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
seen.add(key);
|
|
177
|
+
flattened.push(selector);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
for (const item of list.get('value')) {
|
|
181
|
+
if (isNode(item, N.PseudoSelector) && item.get('name') === ':is' && isNode(item.get('arg'), N.SelectorList)) {
|
|
182
|
+
const arg = item.get('arg');
|
|
183
|
+
if (isNode(arg, N.SelectorList)) {
|
|
184
|
+
for (const child of arg.get('value')) {
|
|
185
|
+
pushUnique(child);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (isNode(item, N.CompoundSelector) && item.get('value').length === 1) {
|
|
192
|
+
const only = item.get('value')[0]!;
|
|
193
|
+
if (isNode(only, N.PseudoSelector) && only.get('name') === ':is' && isNode(only.get('arg'), N.SelectorList)) {
|
|
194
|
+
const arg = only.get('arg');
|
|
195
|
+
if (isNode(arg, N.SelectorList)) {
|
|
196
|
+
for (const child of arg.get('value')) {
|
|
197
|
+
pushUnique(child);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (isNode(item, N.ComplexSelector) && item.get('value').length === 1) {
|
|
205
|
+
const only = item.get('value')[0]!;
|
|
206
|
+
if (isNode(only, N.PseudoSelector) && only.get('name') === ':is' && isNode(only.get('arg'), N.SelectorList)) {
|
|
207
|
+
const arg = only.get('arg');
|
|
208
|
+
if (isNode(arg, N.SelectorList)) {
|
|
209
|
+
for (const child of arg.get('value')) {
|
|
210
|
+
pushUnique(child);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
pushUnique(item);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (flattened.length === list.get('value').length) {
|
|
221
|
+
return list;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return SelectorList.create(flattened).inherit(list);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Wraps a parent selector into the single selector fragment that should appear
|
|
229
|
+
* inside another selector context.
|
|
230
|
+
*
|
|
231
|
+
* A selector list becomes generated `:is(...)` so it can occupy one selector
|
|
232
|
+
* position without AST mutation. Non-lists are copied directly.
|
|
233
|
+
*/
|
|
234
|
+
export function wrapParentSelectorForNestedContext(
|
|
235
|
+
parentSelector: Selector,
|
|
236
|
+
_collapseNesting: boolean = false
|
|
237
|
+
): Selector {
|
|
238
|
+
let parentCopy = parentSelector.copy(true);
|
|
239
|
+
if (isNode(parentCopy, N.SelectorList)) {
|
|
240
|
+
parentCopy = flattenSelectorListAlternatives(parentCopy);
|
|
241
|
+
}
|
|
242
|
+
if (isNode(parentCopy, N.ComplexSelector)) {
|
|
243
|
+
const requiresGrouping = parentCopy.get('value').some(
|
|
244
|
+
part => isNode(part, N.Combinator) && part.valueOf() !== ' '
|
|
245
|
+
);
|
|
246
|
+
if (requiresGrouping) {
|
|
247
|
+
const wrapped = PseudoSelector.create({ name: ':is', arg: parentCopy });
|
|
248
|
+
wrapped.generated = true;
|
|
249
|
+
return wrapped;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (isNode(parentCopy, N.SelectorList)) {
|
|
253
|
+
const wrapped = PseudoSelector.create({ name: ':is', arg: parentCopy });
|
|
254
|
+
wrapped.generated = true;
|
|
255
|
+
return wrapped;
|
|
256
|
+
}
|
|
257
|
+
return parentCopy;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Returns the selector fragment(s) that should replace an authored ampersand.
|
|
262
|
+
*
|
|
263
|
+
* Selector-list parents become generated `:is(...)` wrappers so they can occupy
|
|
264
|
+
* one selector position. Complex parents splice directly only when the
|
|
265
|
+
* ampersand is the leading component of the containing route; otherwise they
|
|
266
|
+
* remain wrapped to preserve route validity.
|
|
267
|
+
*/
|
|
268
|
+
export function getParentReplacementForAmpersand(
|
|
269
|
+
parentSelector: Selector,
|
|
270
|
+
atStart: boolean
|
|
271
|
+
): Selector[] {
|
|
272
|
+
const parentCopy = parentSelector.copy(true);
|
|
273
|
+
|
|
274
|
+
if (isNode(parentCopy, N.SelectorList)) {
|
|
275
|
+
return [wrapParentSelectorForNestedContext(parentCopy)];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (isNode(parentCopy, N.ComplexSelector)) {
|
|
279
|
+
if (atStart) {
|
|
280
|
+
return [...parentCopy.get('value')];
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const wrapped = PseudoSelector.create({
|
|
284
|
+
name: ':is',
|
|
285
|
+
arg: parentCopy
|
|
286
|
+
});
|
|
287
|
+
wrapped.generated = true;
|
|
288
|
+
return [wrapped];
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return [parentCopy];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function selectorHasAuthoredAmpersand(selector: Selector): boolean {
|
|
295
|
+
if (isNode(selector, N.Ampersand)) {
|
|
296
|
+
return !selector.hasFlag(F_IMPLICIT_AMPERSAND);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (isNode(selector, N.SelectorList | N.ComplexSelector | N.CompoundSelector)) {
|
|
300
|
+
return selector.get('value').some(item => selectorHasAuthoredAmpersand(item));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (isNode(selector, N.PseudoSelector)) {
|
|
304
|
+
const arg = (selector as PseudoSelector).get('arg');
|
|
305
|
+
if (arg && isNode(arg, N.Selector)) {
|
|
306
|
+
return selectorHasAuthoredAmpersand(arg);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function selectorContainsGeneratedIs(selector: Selector): boolean {
|
|
314
|
+
if (isNode(selector, N.PseudoSelector)) {
|
|
315
|
+
return selector.generated && selector.get('name') === ':is';
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (isNode(selector, N.SelectorList | N.ComplexSelector | N.CompoundSelector)) {
|
|
319
|
+
return selector.get('value').some(item => selectorContainsGeneratedIs(item));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Apply an ampersand's template (suffix like `-1` or template like `.&-foo`)
|
|
327
|
+
* to a resolved parent selector. Mirrors the logic in Ampersand.evalNode but
|
|
328
|
+
* operates on the already-resolved replacement selector.
|
|
329
|
+
*/
|
|
330
|
+
function applyTemplate(resolved: Selector, template: string, inherit: Selector): Selector {
|
|
331
|
+
const normalizedTemplate = template.replace(ampersandTemplateInterpolationRegex, 'x');
|
|
332
|
+
if (normalizedTemplate === 'nil' || !ampersandTemplateRegex.test(normalizedTemplate)) {
|
|
333
|
+
throw new SyntaxError(`Invalid ampersand template "${template}"`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const isTemplateMerge = template.includes('&');
|
|
337
|
+
if (isTemplateMerge) {
|
|
338
|
+
const isIdentJoinChar = (char: string | undefined): boolean =>
|
|
339
|
+
!!char && /[a-zA-Z0-9_-]/.test(char);
|
|
340
|
+
const assertValidTemplateJoin = (template: string, replacement: string): void => {
|
|
341
|
+
if (!replacement) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
let searchFrom = 0;
|
|
345
|
+
while (true) {
|
|
346
|
+
const idx = template.indexOf('&', searchFrom);
|
|
347
|
+
if (idx === -1) {
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
const before = idx > 0 ? template[idx - 1] : undefined;
|
|
351
|
+
const after = idx < template.length - 1 ? template[idx + 1] : undefined;
|
|
352
|
+
const first = replacement[0];
|
|
353
|
+
const last = replacement[replacement.length - 1];
|
|
354
|
+
const invalidHeadJoin = (first === '.' || first === '#') && isIdentJoinChar(before);
|
|
355
|
+
const invalidTailJoin = (last === '.' || last === '#') && isIdentJoinChar(after);
|
|
356
|
+
if (invalidHeadJoin || invalidTailJoin) {
|
|
357
|
+
throw new SyntaxError(`Invalid ampersand merge template "${template}" with parent selector "${replacement}"`);
|
|
358
|
+
}
|
|
359
|
+
searchFrom = idx + 1;
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
const applyTemplate = (sel: Selector): Selector => {
|
|
363
|
+
const value = sel.toTrimmedString();
|
|
364
|
+
assertValidTemplateJoin(template, value);
|
|
365
|
+
return new BasicSelector(template.split('&').join(value)).inherit(inherit);
|
|
366
|
+
};
|
|
367
|
+
const distributeTemplate = (sel: Selector): Selector => {
|
|
368
|
+
if (
|
|
369
|
+
isNode(sel, N.PseudoSelector)
|
|
370
|
+
&& sel.generated
|
|
371
|
+
&& sel.get('name') === ':is'
|
|
372
|
+
&& isNode(sel.get('arg'), N.SelectorList)
|
|
373
|
+
) {
|
|
374
|
+
const arg = sel.get('arg');
|
|
375
|
+
return isNode(arg, N.Selector) ? distributeTemplate(arg) : sel;
|
|
376
|
+
}
|
|
377
|
+
if (isNode(sel, N.SelectorList)) {
|
|
378
|
+
const items = sel.get('value').map(item => distributeTemplate(item));
|
|
379
|
+
const result = SelectorList.create(
|
|
380
|
+
items.flatMap(item => isNode(item, N.SelectorList) ? item.get('value') : [item])
|
|
381
|
+
).inherit(inherit);
|
|
382
|
+
return result;
|
|
383
|
+
}
|
|
384
|
+
const selectorStr = sel.toTrimmedString();
|
|
385
|
+
if (selectorStr.includes(',')) {
|
|
386
|
+
const parts = selectorStr.split(',').map(s => s.trim()).filter(Boolean);
|
|
387
|
+
const mapped = parts.map((part) => {
|
|
388
|
+
assertValidTemplateJoin(template, part);
|
|
389
|
+
return new BasicSelector(template.split('&').join(part)).inherit(inherit);
|
|
390
|
+
});
|
|
391
|
+
return mapped.length === 1 ? mapped[0]! : SelectorList.create(mapped).inherit(inherit);
|
|
392
|
+
}
|
|
393
|
+
return applyTemplate(sel);
|
|
394
|
+
};
|
|
395
|
+
return distributeTemplate(resolved);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const doAppend = (n: Selector): void => {
|
|
399
|
+
for (const s of n.nodes(true)) {
|
|
400
|
+
if (isNode(s, N.SimpleSelector)) {
|
|
401
|
+
if (isNode(s, N.BasicSelector)) {
|
|
402
|
+
(s as BasicSelector).value = (s as BasicSelector).value + template;
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
throw new SyntaxError(`Cannot append "${template}" to this type of selector`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
throw new SyntaxError(`Cannot append "${template}" to this type of selector`);
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
// Unwrap generated :is(SelectorList) so append distributes to all items
|
|
412
|
+
let target = resolved;
|
|
413
|
+
if (
|
|
414
|
+
isNode(target, N.PseudoSelector)
|
|
415
|
+
&& target.generated
|
|
416
|
+
&& target.get('name') === ':is'
|
|
417
|
+
&& isNode(target.get('arg'), N.SelectorList)
|
|
418
|
+
) {
|
|
419
|
+
const arg = target.get('arg');
|
|
420
|
+
if (isNode(arg, N.Selector)) {
|
|
421
|
+
target = arg;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (isNode(target, N.SelectorList)) {
|
|
425
|
+
target.get('value').forEach(item => doAppend(item));
|
|
426
|
+
} else {
|
|
427
|
+
doAppend(target);
|
|
428
|
+
}
|
|
429
|
+
resolved.hoistToRoot = true;
|
|
430
|
+
return resolved;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function resolveAuthoredAmpersands(
|
|
434
|
+
selector: Selector,
|
|
435
|
+
parentSelector: Selector,
|
|
436
|
+
atTopLevel: boolean = true
|
|
437
|
+
): Selector {
|
|
438
|
+
if (isNode(selector, N.Ampersand)) {
|
|
439
|
+
const template = selector.template;
|
|
440
|
+
if (template instanceof Nil) {
|
|
441
|
+
const nilResult = new Nil().inherit(selector);
|
|
442
|
+
nilResult.hoistToRoot = true;
|
|
443
|
+
return nilResult;
|
|
444
|
+
}
|
|
445
|
+
const replacement = getParentReplacementForAmpersand(parentSelector, true);
|
|
446
|
+
let resolved = replacement.length === 1
|
|
447
|
+
? replacement[0]!
|
|
448
|
+
: ComplexSelector.create(replacement).inherit(selector);
|
|
449
|
+
if (typeof template === 'string' && template) {
|
|
450
|
+
resolved = applyTemplate(resolved, template, selector);
|
|
451
|
+
}
|
|
452
|
+
if (template !== undefined) {
|
|
453
|
+
resolved.hoistToRoot = true;
|
|
454
|
+
}
|
|
455
|
+
return resolved;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (isNode(selector, N.SelectorList)) {
|
|
459
|
+
return SelectorList.create(
|
|
460
|
+
selector.get('value').map(item => resolveAuthoredAmpersands(item, parentSelector))
|
|
461
|
+
).inherit(selector);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// CompoundSelector with leading bare & and ComplexSelector parent at top level:
|
|
465
|
+
// Fuse parent's last part with compound suffix → * b[e] instead of :is(* b)[e]
|
|
466
|
+
// Only at top level — inside a ComplexSelector (e.g. after +), keep :is() wrapping.
|
|
467
|
+
if (atTopLevel && isNode(selector, N.CompoundSelector)) {
|
|
468
|
+
const compoundData = selector.get('value');
|
|
469
|
+
if (
|
|
470
|
+
compoundData.length >= 2
|
|
471
|
+
&& isNode(compoundData[0], N.Ampersand)
|
|
472
|
+
&& !compoundData[0]!.hasFlag(F_IMPLICIT_AMPERSAND)
|
|
473
|
+
&& compoundData[0].isPlainAmpersand()
|
|
474
|
+
&& isNode(parentSelector, N.ComplexSelector)
|
|
475
|
+
) {
|
|
476
|
+
const parentParts = [...parentSelector.get('value')];
|
|
477
|
+
const remaining = compoundData.slice(1).map(d => resolveAuthoredAmpersands(d, parentSelector));
|
|
478
|
+
const lastParentPart = parentParts[parentParts.length - 1]!.clone(false);
|
|
479
|
+
const fusedLast = CompoundSelector.create([lastParentPart, ...remaining]).inherit(selector);
|
|
480
|
+
const prefix = parentParts.slice(0, -1).map(p => p.clone(false));
|
|
481
|
+
if (prefix.length > 0) {
|
|
482
|
+
return ComplexSelector.create([...prefix, fusedLast]).inherit(selector);
|
|
483
|
+
}
|
|
484
|
+
return fusedLast;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (isNode(selector, N.ComplexSelector | N.CompoundSelector)) {
|
|
489
|
+
const selectorData = selector.get('value');
|
|
490
|
+
const nextData: Selector[] = [];
|
|
491
|
+
let hasAppendValue = false;
|
|
492
|
+
const isCompound = isNode(selector, N.CompoundSelector);
|
|
493
|
+
for (let i = 0; i < selectorData.length; i++) {
|
|
494
|
+
const item = selectorData[i];
|
|
495
|
+
if (isNode(item, N.Ampersand) && !item.hasFlag(F_IMPLICIT_AMPERSAND)) {
|
|
496
|
+
const template = item.template;
|
|
497
|
+
const atStart = !isCompound && i === 0;
|
|
498
|
+
if (template instanceof Nil) {
|
|
499
|
+
hasAppendValue = true;
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
const parts = getParentReplacementForAmpersand(parentSelector, atStart);
|
|
503
|
+
if (typeof template === 'string' && template) {
|
|
504
|
+
let resolved = parts.length === 1
|
|
505
|
+
? parts[0]!
|
|
506
|
+
: ComplexSelector.create(parts).inherit(item);
|
|
507
|
+
resolved = applyTemplate(resolved, template, item);
|
|
508
|
+
nextData.push(resolved);
|
|
509
|
+
hasAppendValue = true;
|
|
510
|
+
} else {
|
|
511
|
+
nextData.push(...parts);
|
|
512
|
+
if (template !== undefined) {
|
|
513
|
+
hasAppendValue = true;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
// Fuse complex parent into compound at ComplexSelector start position:
|
|
519
|
+
// e.g. &.foo with parent .a .b → .a .b.foo (not :is(.a .b).foo)
|
|
520
|
+
if (
|
|
521
|
+
!isCompound && i === 0
|
|
522
|
+
&& isNode(item, N.CompoundSelector)
|
|
523
|
+
&& isNode(parentSelector, N.ComplexSelector)
|
|
524
|
+
) {
|
|
525
|
+
const compoundData = item.get('value');
|
|
526
|
+
if (compoundData.length > 0 && isNode(compoundData[0], N.Ampersand) && !compoundData[0]!.hasFlag(F_IMPLICIT_AMPERSAND)) {
|
|
527
|
+
const ampTemplate = compoundData[0].template;
|
|
528
|
+
if (ampTemplate === undefined) {
|
|
529
|
+
const parentParts = [...parentSelector.get('value')];
|
|
530
|
+
const remaining = compoundData.slice(1).map(d => resolveAuthoredAmpersands(d, parentSelector));
|
|
531
|
+
const lastParentPart = parentParts[parentParts.length - 1]!.copy(true);
|
|
532
|
+
const compoundItems = [lastParentPart, ...remaining];
|
|
533
|
+
const fusedLast = CompoundSelector.create(compoundItems).inherit(item);
|
|
534
|
+
const prefix = parentParts.slice(0, -1).map(p => p.copy(true));
|
|
535
|
+
if (prefix.length > 0) {
|
|
536
|
+
nextData.push(...prefix, fusedLast);
|
|
537
|
+
} else {
|
|
538
|
+
nextData.push(fusedLast);
|
|
539
|
+
}
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
nextData.push(resolveAuthoredAmpersands(item, parentSelector, false));
|
|
545
|
+
}
|
|
546
|
+
// For compounds, sort type/element selectors before class/id/pseudo
|
|
547
|
+
if (isCompound) {
|
|
548
|
+
nextData.sort((a, b) => {
|
|
549
|
+
const aIsTag = isNode(a, N.BasicSelector) && a.isTag ? 0 : 1;
|
|
550
|
+
const bIsTag = isNode(b, N.BasicSelector) && b.isTag ? 0 : 1;
|
|
551
|
+
return aIsTag - bIsTag;
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
if (nextData.length === 0) {
|
|
555
|
+
const nilResult = new Nil().inherit(selector);
|
|
556
|
+
nilResult.hoistToRoot = hasAppendValue;
|
|
557
|
+
return nilResult;
|
|
558
|
+
}
|
|
559
|
+
const ctor = !isCompound ? ComplexSelector : CompoundSelector;
|
|
560
|
+
const result = ctor.create(nextData).inherit(selector);
|
|
561
|
+
if (hasAppendValue) {
|
|
562
|
+
result.hoistToRoot = true;
|
|
563
|
+
}
|
|
564
|
+
return result;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (isNode(selector, N.PseudoSelector)) {
|
|
568
|
+
const arg = selector.get('arg');
|
|
569
|
+
if (arg && isNode(arg, N.Selector)) {
|
|
570
|
+
const copy = selector.copy(true);
|
|
571
|
+
const nextArg = resolveAuthoredAmpersands(arg, parentSelector);
|
|
572
|
+
copy.adopt(nextArg);
|
|
573
|
+
copy.arg = nextArg;
|
|
574
|
+
return copy;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
return selector.copy(true);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function composeSelectorRouteWithParent(
|
|
582
|
+
selector: Selector,
|
|
583
|
+
parentSelector: Selector
|
|
584
|
+
): Selector {
|
|
585
|
+
const childCopy = selector.copy(true);
|
|
586
|
+
if (selectorHasAuthoredAmpersand(childCopy)) {
|
|
587
|
+
return resolveAuthoredAmpersands(childCopy, parentSelector);
|
|
588
|
+
}
|
|
589
|
+
const parentParts = getParentReplacementForAmpersand(parentSelector, true);
|
|
590
|
+
|
|
591
|
+
if (isNode(childCopy, N.ComplexSelector)) {
|
|
592
|
+
const nextData = [...parentParts];
|
|
593
|
+
|
|
594
|
+
if (!isNode(childCopy.get('value')[0], N.Combinator)) {
|
|
595
|
+
nextData.push(Combinator.create(' '));
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
nextData.push(...childCopy.get('value'));
|
|
599
|
+
return ComplexSelector.create(nextData).inherit(selector);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return ComplexSelector.create([
|
|
603
|
+
...parentParts,
|
|
604
|
+
Combinator.create(' '),
|
|
605
|
+
childCopy
|
|
606
|
+
]).inherit(selector);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Composes a selector with its parent selector without inserting implicit
|
|
611
|
+
* ampersands or relying on later `:is(...)` cleanup passes.
|
|
612
|
+
*
|
|
613
|
+
* The historical `getImplicitSelector()` name is kept for compatibility with
|
|
614
|
+
* callers and tests, but the implementation is now pure selector composition.
|
|
615
|
+
*
|
|
616
|
+
* - Start-position parent composition follows the same rule as authored `&`:
|
|
617
|
+
* selector-list parents stay one fragment via generated `:is(...)`, while
|
|
618
|
+
* non-list parents splice directly.
|
|
619
|
+
* - Selector-list children keep their list shape after composition.
|
|
620
|
+
* - Selector-list children containing complex items are grouped under one
|
|
621
|
+
* generated `:is(...)` before the parent is composed so the common parent
|
|
622
|
+
* stays shared.
|
|
623
|
+
* @param collapseNesting - Whether to collapse nesting (affects visibility flags)
|
|
624
|
+
* @returns The composed selector
|
|
625
|
+
*/
|
|
626
|
+
export function getImplicitSelector(
|
|
627
|
+
selector: Selector,
|
|
628
|
+
parent: Selector,
|
|
629
|
+
collapseNesting: boolean = false
|
|
630
|
+
): Selector {
|
|
631
|
+
if (isNode(selector, N.Nil)) {
|
|
632
|
+
return selector;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
const parentSelector = parent;
|
|
636
|
+
if (!parentSelector || isNode(parentSelector, N.Nil)) {
|
|
637
|
+
return selector.copy(true);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (isNode(selector, N.SelectorList)) {
|
|
641
|
+
const shouldGroupSelectorListBeforeComposition = (
|
|
642
|
+
!selectorHasAuthoredAmpersand(selector)
|
|
643
|
+
&& (
|
|
644
|
+
!collapseNesting
|
|
645
|
+
? selector.get('value').some(item =>
|
|
646
|
+
isNode(item, N.ComplexSelector) && item.get('value').length > 1
|
|
647
|
+
)
|
|
648
|
+
: (
|
|
649
|
+
!isNode(parentSelector, N.SelectorList)
|
|
650
|
+
&& !selectorContainsGeneratedIs(parentSelector)
|
|
651
|
+
)
|
|
652
|
+
)
|
|
653
|
+
);
|
|
654
|
+
|
|
655
|
+
if (shouldGroupSelectorListBeforeComposition) {
|
|
656
|
+
const grouped = PseudoSelector.create({
|
|
657
|
+
name: ':is',
|
|
658
|
+
arg: selector.copy(true)
|
|
659
|
+
});
|
|
660
|
+
grouped.generated = true;
|
|
661
|
+
selector = composeSelectorRouteWithParent(grouped, parentSelector);
|
|
662
|
+
if (collapseNesting) {
|
|
663
|
+
selector.hoistToRoot = true;
|
|
664
|
+
}
|
|
665
|
+
return selector;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const next = selector.get('value').map(item =>
|
|
669
|
+
composeSelectorRouteWithParent(item, parentSelector)
|
|
670
|
+
);
|
|
671
|
+
const list = SelectorList.create(next).inherit(selector);
|
|
672
|
+
if (collapseNesting) {
|
|
673
|
+
list.hoistToRoot = true;
|
|
674
|
+
}
|
|
675
|
+
return list;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
selector = composeSelectorRouteWithParent(selector, parentSelector);
|
|
679
|
+
|
|
680
|
+
if (collapseNesting) {
|
|
681
|
+
selector.hoistToRoot = true;
|
|
682
|
+
}
|
|
683
|
+
return selector;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Removes one leading parent composition from a selector so nested rulesets can
|
|
688
|
+
* keep rendering local selector shape while their concrete `data.selector`
|
|
689
|
+
* remains fully composed for matching.
|
|
690
|
+
*
|
|
691
|
+
* Only alternatives that actually start with the serialized parent prefix are
|
|
692
|
+
* de-prefixed. Mixed selector lists therefore keep escaped/hoisted alternatives
|
|
693
|
+
* intact while converting same-parent alternatives back to local form.
|
|
694
|
+
*/
|
|
695
|
+
export function localizeSelectorAgainstParent(
|
|
696
|
+
selector: Selector,
|
|
697
|
+
parent: Selector
|
|
698
|
+
): Selector {
|
|
699
|
+
const wrappedParent = wrapParentSelectorForNestedContext(parent, false);
|
|
700
|
+
const parentPrefix = isNode(wrappedParent, N.ComplexSelector)
|
|
701
|
+
? [...wrappedParent.get('value')]
|
|
702
|
+
: [wrappedParent];
|
|
703
|
+
|
|
704
|
+
const stripParentPrefix = (route: Selector): Selector => {
|
|
705
|
+
if (!isNode(route, N.ComplexSelector)) {
|
|
706
|
+
return route.copy(true);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
const data = route.get('value');
|
|
710
|
+
if (data.length <= parentPrefix.length) {
|
|
711
|
+
return route.copy(true);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
for (let i = 0; i < parentPrefix.length; i++) {
|
|
715
|
+
if (data[i]!.valueOf() !== parentPrefix[i]!.valueOf()) {
|
|
716
|
+
return route.copy(true);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const next = data[parentPrefix.length];
|
|
721
|
+
if (!isNode(next, N.Combinator) || next.valueOf() !== ' ') {
|
|
722
|
+
return route.copy(true);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
const remainder = data.slice(parentPrefix.length + 1).map(node => node.copy(true));
|
|
726
|
+
if (remainder.length === 0) {
|
|
727
|
+
return route.copy(true);
|
|
728
|
+
}
|
|
729
|
+
if (remainder.length === 1) {
|
|
730
|
+
return remainder[0]!;
|
|
731
|
+
}
|
|
732
|
+
return ComplexSelector.create(remainder).inherit(route);
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
if (isNode(selector, N.SelectorList)) {
|
|
736
|
+
return SelectorList.create(
|
|
737
|
+
selector.get('value').map(item => stripParentPrefix(item))
|
|
738
|
+
).inherit(selector);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
return stripParentPrefix(selector);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/** Returns true if the selector (or any top-level SelectorList item) has F_EXTENDED. */
|
|
745
|
+
export function hasExtendedSelector(sel: Selector | Nil | undefined, context?: Context): boolean {
|
|
746
|
+
if (!sel || sel instanceof Nil) {
|
|
747
|
+
return false;
|
|
748
|
+
}
|
|
749
|
+
if (isNode(sel, N.SelectorList)) {
|
|
750
|
+
return sel.get('value').some(item =>
|
|
751
|
+
context ? item._hasFlag(F_EXTENDED, context) : item.hasFlag(F_EXTENDED)
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
return context
|
|
755
|
+
? sel._hasFlag(F_EXTENDED, context)
|
|
756
|
+
: sel.hasFlag(F_EXTENDED);
|
|
757
|
+
}
|