@jesscss/core 2.0.0-alpha.5 → 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 -98
- package/lib/tree/ampersand.d.ts.map +0 -1
- package/lib/tree/ampersand.js +0 -319
- 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,226 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { Context } from '../../../context.js';
|
|
3
|
+
import { tryExtendSelector } from '../extend-core.js';
|
|
4
|
+
import {
|
|
5
|
+
rules,
|
|
6
|
+
ruleset,
|
|
7
|
+
extend,
|
|
8
|
+
el,
|
|
9
|
+
compound,
|
|
10
|
+
sellist,
|
|
11
|
+
sel,
|
|
12
|
+
co,
|
|
13
|
+
pseudo,
|
|
14
|
+
ExtendFlag,
|
|
15
|
+
type Ruleset
|
|
16
|
+
} from '../../index.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* processExtends behavior is tested via the real eval flow: build AST as the parser would
|
|
20
|
+
* (rules with rulesets that contain extend() nodes), call root.eval(context), then assert.
|
|
21
|
+
* No manual context.root, context.extendRoots.registerRoot, or context.extends.push.
|
|
22
|
+
*/
|
|
23
|
+
describe('processExtends function (eval flow)', () => {
|
|
24
|
+
describe('Basic extend processing', () => {
|
|
25
|
+
it('should extend a simple ruleset', async () => {
|
|
26
|
+
const root = rules([
|
|
27
|
+
ruleset({ selector: el('.foo'), rules: rules([]) }),
|
|
28
|
+
ruleset({
|
|
29
|
+
selector: el('.bar'),
|
|
30
|
+
rules: rules([extend({ target: el('.foo') })])
|
|
31
|
+
})
|
|
32
|
+
]);
|
|
33
|
+
const context = new Context();
|
|
34
|
+
const evald = await root.eval(context);
|
|
35
|
+
const firstRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
36
|
+
expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo,.bar');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should handle multiple extends on same target', async () => {
|
|
40
|
+
const root = rules([
|
|
41
|
+
ruleset({ selector: el('.foo'), rules: rules([]) }),
|
|
42
|
+
ruleset({
|
|
43
|
+
selector: el('.bar'),
|
|
44
|
+
rules: rules([extend({ target: el('.foo') })])
|
|
45
|
+
}),
|
|
46
|
+
ruleset({
|
|
47
|
+
selector: el('.baz'),
|
|
48
|
+
rules: rules([extend({ target: el('.foo') })])
|
|
49
|
+
})
|
|
50
|
+
]);
|
|
51
|
+
const context = new Context();
|
|
52
|
+
const evald = await root.eval(context);
|
|
53
|
+
const firstRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
54
|
+
expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo,.bar,.baz');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should skip self-referencing extends', async () => {
|
|
58
|
+
const root = rules([
|
|
59
|
+
ruleset({
|
|
60
|
+
selector: el('.foo'),
|
|
61
|
+
rules: rules([extend({ target: el('.foo') })])
|
|
62
|
+
})
|
|
63
|
+
]);
|
|
64
|
+
const context = new Context();
|
|
65
|
+
const evald = await root.eval(context);
|
|
66
|
+
const firstRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
67
|
+
expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('Extend chaining', () => {
|
|
72
|
+
it('should chain extends when extended selector matches another target', async () => {
|
|
73
|
+
const root = rules([
|
|
74
|
+
ruleset({ selector: el('.foo'), rules: rules([]) }),
|
|
75
|
+
ruleset({
|
|
76
|
+
selector: el('.bar'),
|
|
77
|
+
rules: rules([extend({ target: el('.foo') })])
|
|
78
|
+
}),
|
|
79
|
+
ruleset({
|
|
80
|
+
selector: el('.baz'),
|
|
81
|
+
rules: rules([extend({ target: el('.bar') })])
|
|
82
|
+
})
|
|
83
|
+
]);
|
|
84
|
+
const context = new Context();
|
|
85
|
+
const evald = await root.eval(context);
|
|
86
|
+
const firstRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
87
|
+
expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo,.bar,.baz');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('Partial extends', () => {
|
|
92
|
+
it('should handle partial extends with all flag', async () => {
|
|
93
|
+
const targetSelector = compound([el('.a'), el('.b')]);
|
|
94
|
+
const extendSelector = el('.c');
|
|
95
|
+
const root = rules([
|
|
96
|
+
ruleset({
|
|
97
|
+
selector: targetSelector,
|
|
98
|
+
rules: rules([])
|
|
99
|
+
}),
|
|
100
|
+
ruleset({
|
|
101
|
+
selector: extendSelector,
|
|
102
|
+
rules: rules([extend({ target: el('.b'), flag: ExtendFlag.All })])
|
|
103
|
+
})
|
|
104
|
+
]);
|
|
105
|
+
const context = new Context();
|
|
106
|
+
const evald = await root.eval(context);
|
|
107
|
+
const firstRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
108
|
+
const expected = tryExtendSelector(
|
|
109
|
+
targetSelector.copy(true),
|
|
110
|
+
el('.b'),
|
|
111
|
+
extendSelector.copy(true),
|
|
112
|
+
true
|
|
113
|
+
);
|
|
114
|
+
expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe(expected.value.valueOf());
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should apply partial extends to the outer ruleset selector when partial is true (Less `all`)', async () => {
|
|
118
|
+
const targetSelector = sellist([
|
|
119
|
+
compound([el('.replace'), el('.replace')]),
|
|
120
|
+
sel([compound([el('.c'), el('.replace')]), co('+'), el('.replace')])
|
|
121
|
+
]);
|
|
122
|
+
const extendSelector = el('.rep_ace');
|
|
123
|
+
const outerRules = rules([
|
|
124
|
+
ruleset({
|
|
125
|
+
selector: sellist([el('.replace'), el('.c')]),
|
|
126
|
+
rules: rules([])
|
|
127
|
+
})
|
|
128
|
+
]);
|
|
129
|
+
const root = rules([
|
|
130
|
+
ruleset({
|
|
131
|
+
selector: targetSelector,
|
|
132
|
+
rules: outerRules
|
|
133
|
+
}),
|
|
134
|
+
ruleset({
|
|
135
|
+
selector: extendSelector,
|
|
136
|
+
rules: rules([extend({ target: el('.replace'), flag: ExtendFlag.All })])
|
|
137
|
+
})
|
|
138
|
+
]);
|
|
139
|
+
const context = new Context();
|
|
140
|
+
const evald = await root.eval(context);
|
|
141
|
+
const outerRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
142
|
+
const nestedRuleset = outerRuleset?.get('rules')?.value?.[0];
|
|
143
|
+
const expected = tryExtendSelector(
|
|
144
|
+
targetSelector.copy(true),
|
|
145
|
+
el('.replace'),
|
|
146
|
+
extendSelector.copy(true),
|
|
147
|
+
true
|
|
148
|
+
);
|
|
149
|
+
expect(outerRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe(expected.value.valueOf());
|
|
150
|
+
// Nested selectors stay defined and keep their existing structure.
|
|
151
|
+
const nestedSel = nestedRuleset?.selector?.valueOf() ?? '';
|
|
152
|
+
expect(nestedSel).toContain('.replace');
|
|
153
|
+
expect(nestedSel).toContain('.c');
|
|
154
|
+
expect(nestedSel.length).toBeGreaterThan(0);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should apply multiple partial extends in sequence', async () => {
|
|
158
|
+
const targetSelector = sellist([
|
|
159
|
+
sel([el('.foo'), co(' '), el('.bar')]),
|
|
160
|
+
sel([el('.foo'), co(' '), el('.baz')])
|
|
161
|
+
]);
|
|
162
|
+
const firstExtend = sel([el('.ext1'), co(' '), el('.ext2')]);
|
|
163
|
+
const secondExtend = pseudo({ name: ':is', arg: sellist([el('.ext3'), el('.ext4')]) });
|
|
164
|
+
const root = rules([
|
|
165
|
+
ruleset({
|
|
166
|
+
selector: targetSelector,
|
|
167
|
+
rules: rules([])
|
|
168
|
+
}),
|
|
169
|
+
ruleset({
|
|
170
|
+
selector: firstExtend,
|
|
171
|
+
rules: rules([extend({ target: el('.foo'), flag: ExtendFlag.All })])
|
|
172
|
+
}),
|
|
173
|
+
ruleset({
|
|
174
|
+
selector: secondExtend,
|
|
175
|
+
rules: rules([extend({ target: el('.foo'), flag: ExtendFlag.All })])
|
|
176
|
+
})
|
|
177
|
+
]);
|
|
178
|
+
const context = new Context();
|
|
179
|
+
const evald = await root.eval(context);
|
|
180
|
+
const firstRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
181
|
+
const output = firstRuleset?.getEffectiveSelector?.(false, context).valueOf() ?? '';
|
|
182
|
+
expect(output).toContain('.ext1 .ext2');
|
|
183
|
+
expect(output).toContain('.ext3,.ext4');
|
|
184
|
+
expect(output).toContain('.bar');
|
|
185
|
+
expect(output).toContain('.baz');
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('shouldSkipRuleset logic', () => {
|
|
190
|
+
it('should skip extending ruleset that contains the extend as a child', async () => {
|
|
191
|
+
// .foo { extend(.foo) } only - the extend node is inside .foo, so we must not modify .foo (self-modification guard)
|
|
192
|
+
const root = rules([
|
|
193
|
+
ruleset({
|
|
194
|
+
selector: el('.foo'),
|
|
195
|
+
rules: rules([extend({ target: el('.foo') })])
|
|
196
|
+
})
|
|
197
|
+
]);
|
|
198
|
+
const context = new Context();
|
|
199
|
+
const evald = await root.eval(context);
|
|
200
|
+
const firstRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
201
|
+
expect(firstRuleset?.getEffectiveSelector?.(false, context).valueOf()).toBe('.foo');
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe('Phase 2 iterative processing', () => {
|
|
206
|
+
it('should process extended rulesets in Phase 2', async () => {
|
|
207
|
+
const root = rules([
|
|
208
|
+
ruleset({ selector: el('.foo'), rules: rules([]) }),
|
|
209
|
+
ruleset({
|
|
210
|
+
selector: el('.bar'),
|
|
211
|
+
rules: rules([extend({ target: el('.foo') })])
|
|
212
|
+
}),
|
|
213
|
+
ruleset({
|
|
214
|
+
selector: el('.baz'),
|
|
215
|
+
rules: rules([extend({ target: el('.bar') })])
|
|
216
|
+
})
|
|
217
|
+
]);
|
|
218
|
+
const context = new Context();
|
|
219
|
+
const evald = await root.eval(context);
|
|
220
|
+
const fooRuleset = evald.at(0, context) as Ruleset | undefined;
|
|
221
|
+
const barRuleset = evald.at(1, context) as Ruleset | undefined;
|
|
222
|
+
expect(fooRuleset?.getEffectiveSelector?.(false, context).valueOf()).toContain('.bar');
|
|
223
|
+
expect(barRuleset?.getEffectiveSelector?.(false, context).valueOf()).toContain('.baz');
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
});
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { el, sel, sellist, compound, co, pseudo, attr, PseudoSelector, amp, rules, ruleset, any } from '../../index.js';
|
|
3
|
+
import { processLeadingIs } from '../process-leading-is.js';
|
|
4
|
+
import { isNode } from '../is-node.js';
|
|
5
|
+
import { N } from '../../node-type.js';
|
|
6
|
+
import type { Selector } from '../../selector.js';
|
|
7
|
+
import { Context } from '../../../context.js';
|
|
8
|
+
import { F_IMPLICIT_AMPERSAND } from '../../node.js';
|
|
9
|
+
|
|
10
|
+
/** PseudoSelector.create (Node.create) sets generated so processLeadingIs can unwrap. */
|
|
11
|
+
function generatedIs(selector: Selector) {
|
|
12
|
+
const p = (PseudoSelector as any).create({ name: ':is', arg: selector as any });
|
|
13
|
+
expect(p.generated, 'PseudoSelector.create must set generated').toBe(true);
|
|
14
|
+
return p as ReturnType<typeof pseudo>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Stringify processLeadingIs result for toBeString comparison */
|
|
18
|
+
function out(result: Selector | Selector[]): string {
|
|
19
|
+
return Array.isArray(result) ? result.map(s => (s as Selector).valueOf()).join(', ') : (result as Selector).valueOf();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('processLeadingIs', () => {
|
|
23
|
+
describe('does not unwrap when :is is not generated', () => {
|
|
24
|
+
it('leaves non-generated :is(SelectorList) as-is', () => {
|
|
25
|
+
const list = sellist([el('.a'), el('.b')]);
|
|
26
|
+
const isPseudo = pseudo({ name: ':is', arg: list });
|
|
27
|
+
expect((isPseudo).generated).toBeFalsy();
|
|
28
|
+
const result = processLeadingIs(isPseudo);
|
|
29
|
+
expect(result).toBe(isPseudo);
|
|
30
|
+
expect(out(result as Selector)).toBeString(`:is(.a,.b)`);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('leaves non-generated :is(simple) as-is', () => {
|
|
34
|
+
const isPseudo = pseudo({ name: ':is', arg: el('.x') });
|
|
35
|
+
const result = processLeadingIs(isPseudo);
|
|
36
|
+
expect(result).toBe(isPseudo);
|
|
37
|
+
expect(out(result as Selector)).toBeString(`:is(.x)`);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('single generated :is()', () => {
|
|
42
|
+
it('unwraps generated :is(simple) to the inner selector', () => {
|
|
43
|
+
const inner = el('.x');
|
|
44
|
+
const isPseudo = generatedIs(inner);
|
|
45
|
+
const result = processLeadingIs(isPseudo);
|
|
46
|
+
expect(Array.isArray(result)).toBe(false);
|
|
47
|
+
expect(out(result as Selector)).toBeString(`.x`);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('unwraps generated :is(SelectorList) at top level to SelectorList when multiple items', () => {
|
|
51
|
+
const list = sellist([el('.a'), el('.b')]);
|
|
52
|
+
const isPseudo = generatedIs(list);
|
|
53
|
+
const result = processLeadingIs(isPseudo);
|
|
54
|
+
expect(Array.isArray(result)).toBe(false);
|
|
55
|
+
expect(out(result as Selector)).toBeString(`.a,.b`);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('unwraps generated :is(SelectorList) at top level to single selector when one item', () => {
|
|
59
|
+
const list = sellist([el('.a')]);
|
|
60
|
+
const isPseudo = generatedIs(list);
|
|
61
|
+
const result = processLeadingIs(isPseudo);
|
|
62
|
+
expect(Array.isArray(result)).toBe(false);
|
|
63
|
+
expect(out(result as Selector)).toBeString(`.a`);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('returns array when inSelectorList and generated :is(SelectorList)', () => {
|
|
67
|
+
const list = sellist([el('.a'), el('.b')]);
|
|
68
|
+
const isPseudo = generatedIs(list);
|
|
69
|
+
const result = processLeadingIs(isPseudo, { inSelectorList: true });
|
|
70
|
+
expect(Array.isArray(result)).toBe(true);
|
|
71
|
+
expect(out(result as Selector[])).toBeString(`.a, .b`);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('SelectorList', () => {
|
|
76
|
+
it('flattens list items that are generated :is(SelectorList) when inSelectorList', () => {
|
|
77
|
+
const item1 = el('.x');
|
|
78
|
+
const item2 = generatedIs(sellist([el('.a'), el('.b')]));
|
|
79
|
+
const list = sellist([item1, item2]);
|
|
80
|
+
const result = processLeadingIs(list, { inSelectorList: false });
|
|
81
|
+
expect(out(result as Selector)).toBeString(`.x,.a,.b`);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('returns single selector when list has one item after processing', () => {
|
|
85
|
+
const inner = el('.only');
|
|
86
|
+
const isPseudo = generatedIs(inner);
|
|
87
|
+
const list = sellist([isPseudo]);
|
|
88
|
+
const result = processLeadingIs(list);
|
|
89
|
+
expect(Array.isArray(result)).toBe(false);
|
|
90
|
+
expect(out(result as Selector)).toBeString(`.only`);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('CompoundSelector with generated :is as first component', () => {
|
|
95
|
+
/**
|
|
96
|
+
* Same initial AST as Less/CSS parser for `* b { &[e] { } }`:
|
|
97
|
+
* - Parser: qualifiedRule → selectorList → (single) complexSelector for `* b` → [BasicSelector(*), Combinator(' '), BasicSelector(b)].
|
|
98
|
+
* selectorList returns the single item, so ruleset.selector = ComplexSelector (not SelectorList).
|
|
99
|
+
* - Parser: inner qualifiedRule → selectorList → (single) complexSelector for `&[e]` → compoundSelector → [Ampersand, AttributeSelector(e)].
|
|
100
|
+
* compoundSelector with 2 items returns CompoundSelector; complexSelector returns it; selectorList returns it.
|
|
101
|
+
* So we build the same: frame selector = sel([el('*'), co(' '), el('b')]) (ComplexSelector), inner = compound([amp(), attr({ name: 'e' })]) (CompoundSelector).
|
|
102
|
+
* Eval produces compound with first component :is(* b); ampersand sets .generated so processLeadingIs unwraps to * b[e].
|
|
103
|
+
*/
|
|
104
|
+
it('accepts evaled &[e] with frame * b already materialized to * b[e] (same path as ruleset)', async () => {
|
|
105
|
+
const parentSelector = sel([el('*'), co(' '), el('b')]) as any;
|
|
106
|
+
const frameRuleset = ruleset({ selector: parentSelector, rules: rules([]) });
|
|
107
|
+
const innerSelector = compound([amp(), attr({ name: 'e' })]);
|
|
108
|
+
const context = new Context({ collapseNesting: true });
|
|
109
|
+
context.rulesetFrames.push(frameRuleset);
|
|
110
|
+
const evaled = await (innerSelector as any).eval(context);
|
|
111
|
+
expect(isNode(evaled, N.CompoundSelector)).toBe(true);
|
|
112
|
+
const first = (evaled as any).value[0];
|
|
113
|
+
expect(isNode(first, N.ComplexSelector)).toBe(true);
|
|
114
|
+
expect(out(evaled as Selector)).toBeString(`* b[e]`);
|
|
115
|
+
const result = processLeadingIs(evaled as Selector);
|
|
116
|
+
expect(out(result as Selector)).toBeString(`* b[e]`);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('unwraps :is(complex) and merges suffix into last part of complex', () => {
|
|
120
|
+
const complex = sel([el('.menu'), co(' '), el('.menu')]);
|
|
121
|
+
const comp = compound([generatedIs(complex as any), el('li')]);
|
|
122
|
+
const result = processLeadingIs(comp);
|
|
123
|
+
expect(out(result as Selector)).toBeString(`.menu li.menu`);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('unwraps :is(* b)[e] to * b[e] (complex parent + attribute suffix; css-3 nesting case)', () => {
|
|
127
|
+
const complex = sel([el('*'), co(' '), el('b')]);
|
|
128
|
+
const comp = compound([generatedIs(complex as any), attr({ name: 'e' })]);
|
|
129
|
+
const result = processLeadingIs(comp);
|
|
130
|
+
expect(out(result as Selector)).toBeString(`* b[e]`);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('does not unwrap when :is arg is SelectorList', () => {
|
|
134
|
+
const list = sellist([el('.a'), el('.b')]);
|
|
135
|
+
const comp = compound([generatedIs(list), el('li')]);
|
|
136
|
+
const result = processLeadingIs(comp);
|
|
137
|
+
expect(result).toBe(comp);
|
|
138
|
+
expect(out(result as Selector)).toBeString(`:is(.a,.b)li`);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('ComplexSelector with generated :is as first visual component', () => {
|
|
143
|
+
it('unwraps :is(ComplexSelector) into complex components', () => {
|
|
144
|
+
const inner = sel([el('.menu'), co(' '), el('.menu')]);
|
|
145
|
+
const complex = sel([generatedIs(inner as any), co(' '), el('.menu'), co('>'), el('li')]);
|
|
146
|
+
const result = processLeadingIs(complex as any);
|
|
147
|
+
expect(out(result as Selector)).toBeString(`.menu .menu .menu>li`);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('unwraps :is(simple) as first component to single selector + rest', () => {
|
|
151
|
+
const inner = el('.x');
|
|
152
|
+
const complex = sel([generatedIs(inner), co(' '), el('.y')]);
|
|
153
|
+
const result = processLeadingIs(complex as any);
|
|
154
|
+
expect(out(result as Selector)).toBeString(`.x .y`);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('does not unwrap when :is arg is SelectorList', () => {
|
|
158
|
+
const list = sellist([el('.a'), el('.b')]);
|
|
159
|
+
const complex = sel([generatedIs(list), co(' '), el('.y')]);
|
|
160
|
+
const result = processLeadingIs(complex as any);
|
|
161
|
+
expect(result).toBe(complex);
|
|
162
|
+
expect(out(result as Selector)).toBeString(`:is(.a,.b) .y`);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe('implicit ampersand + generated :is(SelectorList)', () => {
|
|
167
|
+
it('unwraps to selector list when shape is implicit-& + generated :is(list)', () => {
|
|
168
|
+
const ampNode = amp({ selectorContainer: { selector: el('.base') } });
|
|
169
|
+
(ampNode as any).addFlag(F_IMPLICIT_AMPERSAND);
|
|
170
|
+
const listArg = sellist([
|
|
171
|
+
sel([el('.base'), co(' '), el('.x')]),
|
|
172
|
+
sel([el('.base'), co(' '), el('.y')])
|
|
173
|
+
]);
|
|
174
|
+
const selector = sel([ampNode, co(' '), generatedIs(listArg)]);
|
|
175
|
+
const result = processLeadingIs(selector as any);
|
|
176
|
+
expect(Array.isArray(result)).toBe(false);
|
|
177
|
+
expect(out(result as Selector)).toBeString(`.x,.y`);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('removes generated :is(list) wrapper in non-header special case', () => {
|
|
181
|
+
const ampNode = amp({ selectorContainer: { selector: el('.base') } });
|
|
182
|
+
(ampNode as any).addFlag(F_IMPLICIT_AMPERSAND);
|
|
183
|
+
const listArg = sellist([
|
|
184
|
+
sel([el('.base'), co(' '), el('.x')]),
|
|
185
|
+
sel([el('.base'), co(' '), el('.y')])
|
|
186
|
+
]);
|
|
187
|
+
const selector = sel([ampNode, co(' '), generatedIs(listArg), co(' '), el('.tail')]);
|
|
188
|
+
const result = processLeadingIs(selector as any);
|
|
189
|
+
expect(Array.isArray(result)).toBe(false);
|
|
190
|
+
expect(out(result as Selector)).not.toContain(':is(');
|
|
191
|
+
expect(out(result as Selector)).toContain('.tail');
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe('does not recurse into pseudo args', () => {
|
|
196
|
+
it('unwraps outer generated :is once; inner :is is returned as arg (not recursively unwrapped)', () => {
|
|
197
|
+
const innerIs = pseudo({ name: ':is', arg: el('.inner') });
|
|
198
|
+
innerIs.generated = true;
|
|
199
|
+
const outer = generatedIs(innerIs);
|
|
200
|
+
const result = processLeadingIs(outer);
|
|
201
|
+
expect(Array.isArray(result)).toBe(false);
|
|
202
|
+
expect(out(result as Selector)).toBeString(`:is(.inner)`);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CallMap } from '../recursion-helper.js';
|
|
3
|
+
import { call, list, num, ref } from '../../index.js';
|
|
4
|
+
|
|
5
|
+
describe('CallMap', () => {
|
|
6
|
+
describe('add', () => {
|
|
7
|
+
it('should return true when the same call is added twice with undefined', () => {
|
|
8
|
+
const callMap = new CallMap();
|
|
9
|
+
const call1 = call({
|
|
10
|
+
name: ref('mixin'),
|
|
11
|
+
args: undefined
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// First call with undefined - should return false
|
|
15
|
+
expect(callMap.add(call1, undefined)).toBe(false);
|
|
16
|
+
|
|
17
|
+
// Second call with undefined - should return true
|
|
18
|
+
expect(callMap.add(call1, undefined)).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should return false when different calls are added with undefined', () => {
|
|
22
|
+
const callMap = new CallMap();
|
|
23
|
+
const call1 = call({
|
|
24
|
+
name: ref('mixin1'),
|
|
25
|
+
args: undefined
|
|
26
|
+
});
|
|
27
|
+
const call2 = call({
|
|
28
|
+
name: ref('mixin2'),
|
|
29
|
+
args: undefined
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// First call with undefined
|
|
33
|
+
expect(callMap.add(call1, undefined)).toBe(false);
|
|
34
|
+
|
|
35
|
+
// Different call with undefined - should return false
|
|
36
|
+
expect(callMap.add(call2, undefined)).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should return true when the same call is added twice with the same list instance', () => {
|
|
40
|
+
const callMap = new CallMap();
|
|
41
|
+
const list1 = list([num(1), num(2)]);
|
|
42
|
+
const call1 = call({
|
|
43
|
+
name: ref('mixin'),
|
|
44
|
+
args: list1.get('value') as any
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// First call with list1
|
|
48
|
+
expect(callMap.add(call1, list1)).toBe(false);
|
|
49
|
+
|
|
50
|
+
// Second call with same list instance - should return true
|
|
51
|
+
expect(callMap.add(call1, list1)).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should return true when the same call is added with identical lists (different instances)', () => {
|
|
55
|
+
const callMap = new CallMap();
|
|
56
|
+
const list1 = list([num(1), num(2)]);
|
|
57
|
+
const list2 = list([num(1), num(2)]); // Same content, different instance
|
|
58
|
+
const call1 = call({
|
|
59
|
+
name: ref('mixin'),
|
|
60
|
+
args: list1.get('value') as any
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// First call with list1
|
|
64
|
+
expect(callMap.add(call1, list1)).toBe(false);
|
|
65
|
+
|
|
66
|
+
// Second call with list2 (different instance, same value) - should return true
|
|
67
|
+
expect(callMap.add(call1, list2)).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should return false when the same call is added with different lists', () => {
|
|
71
|
+
const callMap = new CallMap();
|
|
72
|
+
const list1 = list([num(1), num(2)]);
|
|
73
|
+
const list2 = list([num(3), num(4)]); // Different content
|
|
74
|
+
const call1 = call({
|
|
75
|
+
name: ref('mixin'),
|
|
76
|
+
args: list1.get('value') as any
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// First call with list1
|
|
80
|
+
expect(callMap.add(call1, list1)).toBe(false);
|
|
81
|
+
|
|
82
|
+
// Second call with list2 (different content) - should return false
|
|
83
|
+
expect(callMap.add(call1, list2)).toBe(false);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should prevent a call from calling itself with the same params', () => {
|
|
87
|
+
const callMap = new CallMap();
|
|
88
|
+
const list1 = list([num(1), num(2)]);
|
|
89
|
+
const call1 = call({
|
|
90
|
+
name: ref('mixin'),
|
|
91
|
+
args: list1.get('value') as any
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// First call - should return false
|
|
95
|
+
expect(callMap.add(call1, list1)).toBe(false);
|
|
96
|
+
|
|
97
|
+
// Same call with same params - should return true (recursion detected)
|
|
98
|
+
expect(callMap.add(call1, list1)).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should prevent different calls from calling each other with the same params', () => {
|
|
102
|
+
const callMap = new CallMap();
|
|
103
|
+
const list1 = list([num(1), num(2)]);
|
|
104
|
+
const call1 = call({
|
|
105
|
+
name: ref('mixin1'),
|
|
106
|
+
args: list1.get('value') as any
|
|
107
|
+
});
|
|
108
|
+
const call2 = call({
|
|
109
|
+
name: ref('mixin2'),
|
|
110
|
+
args: list1.get('value') as any
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// First call with list1
|
|
114
|
+
expect(callMap.add(call1, list1)).toBe(false);
|
|
115
|
+
|
|
116
|
+
// Different call with same params - should return false
|
|
117
|
+
// (each call tracks its own args separately)
|
|
118
|
+
expect(callMap.add(call2, list1)).toBe(false);
|
|
119
|
+
|
|
120
|
+
// But if call2 calls itself with same params, it should return true
|
|
121
|
+
expect(callMap.add(call2, list1)).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe('delete', () => {
|
|
126
|
+
it('should remove the last entry for a call', () => {
|
|
127
|
+
const callMap = new CallMap();
|
|
128
|
+
const list1 = list([num(1), num(2)]);
|
|
129
|
+
const call1 = call({
|
|
130
|
+
name: ref('mixin'),
|
|
131
|
+
args: list1.get('value') as any
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Add once - this adds the entry to the set
|
|
135
|
+
callMap.add(call1, list1);
|
|
136
|
+
|
|
137
|
+
// Add again - this checks but doesn't add (only one entry exists)
|
|
138
|
+
expect(callMap.add(call1, list1)).toBe(true);
|
|
139
|
+
|
|
140
|
+
// Delete once - removes the only entry
|
|
141
|
+
expect(callMap.delete(call1)).toBe(true);
|
|
142
|
+
|
|
143
|
+
// Now should return false (no entries)
|
|
144
|
+
expect(callMap.add(call1, list1)).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should handle multiple entries for a call', () => {
|
|
148
|
+
const callMap = new CallMap();
|
|
149
|
+
const list1 = list([num(1), num(2)]);
|
|
150
|
+
const list2 = list([num(3), num(4)]);
|
|
151
|
+
const call1 = call({
|
|
152
|
+
name: ref('mixin'),
|
|
153
|
+
args: list1.get('value') as any
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Add first list
|
|
157
|
+
callMap.add(call1, list1);
|
|
158
|
+
|
|
159
|
+
// Manually add second list to the set (simulating multiple calls)
|
|
160
|
+
// Note: The current implementation doesn't add new args on subsequent calls,
|
|
161
|
+
// so we need to test the delete behavior with multiple entries differently
|
|
162
|
+
const set = (callMap as any)._callMap.get(call1);
|
|
163
|
+
if (set) {
|
|
164
|
+
set.push(list2);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Delete once - should remove the last entry (list2)
|
|
168
|
+
expect(callMap.delete(call1)).toBe(true);
|
|
169
|
+
|
|
170
|
+
// Should still return true for list1
|
|
171
|
+
expect(callMap.add(call1, list1)).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should return false when deleting a non-existent call', () => {
|
|
175
|
+
const callMap = new CallMap();
|
|
176
|
+
const call1 = call({
|
|
177
|
+
name: ref('mixin'),
|
|
178
|
+
args: undefined
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
expect(callMap.delete(call1)).toBe(false);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|