@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,941 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { amp, co, compound, el, is, pseudo, sel, sellist } from '../../../index.js';
|
|
3
|
+
import { ExtendErrorType, tryExtendSelector } from '../extend-core.js';
|
|
4
|
+
|
|
5
|
+
function serialize(selector: { toString(): string }) {
|
|
6
|
+
return selector.toString().trim().replace(/\s*,\s*/g, ', ');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
describe('tryExtendSelector', () => {
|
|
10
|
+
it('returns success result for an exact matching extend', () => {
|
|
11
|
+
const target = el('.a');
|
|
12
|
+
const result = tryExtendSelector(target, el('.a'), el('.b'), false);
|
|
13
|
+
|
|
14
|
+
expect(result.error).toBeUndefined();
|
|
15
|
+
expect(serialize(result.value)).toBe('.a, .b');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('returns NOT_FOUND when an exact extend does not match', () => {
|
|
19
|
+
const target = el('.a');
|
|
20
|
+
const result = tryExtendSelector(target, el('.z'), el('.b'), false);
|
|
21
|
+
|
|
22
|
+
expect(result.value).toBe(target);
|
|
23
|
+
expect(result.error?.type).toBe(ExtendErrorType.NOT_FOUND);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('appends an exact match into an existing selector list', () => {
|
|
27
|
+
const target = sellist([el('.a'), el('.b')]);
|
|
28
|
+
const result = tryExtendSelector(target, el('.a'), el('.c'), false);
|
|
29
|
+
|
|
30
|
+
expect(result.error).toBeUndefined();
|
|
31
|
+
expect(result.value).not.toBe(target);
|
|
32
|
+
expect(serialize(result.value)).toBe('.a, .b, .c');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('appends an exact match into a sole :is() selector', () => {
|
|
36
|
+
const target = is(sellist([el('.a'), el('.b')]));
|
|
37
|
+
const result = tryExtendSelector(target, el('.a'), el('.c'), false);
|
|
38
|
+
|
|
39
|
+
expect(result.error).toBeUndefined();
|
|
40
|
+
expect(result.value).not.toBe(target);
|
|
41
|
+
expect(serialize(result.value)).toBe(':is(.a, .b, .c)');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('resolves a crossed leading ampersand before exact extend output', () => {
|
|
45
|
+
const parent = el('.parent');
|
|
46
|
+
const target = sel([amp(), co(' '), el('.child')]);
|
|
47
|
+
const find = sel([el('.parent'), co(' '), el('.child')]);
|
|
48
|
+
const result = tryExtendSelector(target, find, el('.other'), false, parent);
|
|
49
|
+
|
|
50
|
+
expect(result.error).toBeUndefined();
|
|
51
|
+
expect(result.value.hoistToRoot).toBeFalsy();
|
|
52
|
+
expect(serialize(result.value)).toBe('.parent .child, .other');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('materializes an implicit parent boundary before exact extend output', () => {
|
|
56
|
+
const parent = el('.parent');
|
|
57
|
+
const target = el('.child');
|
|
58
|
+
const find = sel([el('.parent'), co(' '), el('.child')]);
|
|
59
|
+
const result = tryExtendSelector(target, find, el('.other'), false, parent);
|
|
60
|
+
|
|
61
|
+
expect(result.error).toBeUndefined();
|
|
62
|
+
expect(result.value.hoistToRoot).toBeFalsy();
|
|
63
|
+
expect(serialize(result.value)).toBe('.parent .child, .other');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('wraps a selector-list parent before exact extend output', () => {
|
|
67
|
+
const parent = sellist([el('div'), el('span')]);
|
|
68
|
+
const target = sel([amp(), co(' '), el('.child')]);
|
|
69
|
+
const find = sel([el('span'), co(' '), el('.child')]);
|
|
70
|
+
const result = tryExtendSelector(target, find, el('.other'), false, parent);
|
|
71
|
+
|
|
72
|
+
expect(result.error).toBeUndefined();
|
|
73
|
+
expect(result.value.hoistToRoot).toBeFalsy();
|
|
74
|
+
expect(serialize(result.value)).toBe(':is(div, span) .child, .other');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('splices in a leading complex parent before exact extend output', () => {
|
|
78
|
+
const parent = sel([el('.grand'), co('>'), el('.parent')]);
|
|
79
|
+
const target = sel([amp(), co(' '), el('.child')]);
|
|
80
|
+
const find = sel([el('.grand'), co('>'), el('.parent'), co(' '), el('.child')]);
|
|
81
|
+
const result = tryExtendSelector(target, find, el('.other'), false, parent);
|
|
82
|
+
|
|
83
|
+
expect(result.error).toBeUndefined();
|
|
84
|
+
expect(result.value.hoistToRoot).toBeFalsy();
|
|
85
|
+
expect(serialize(result.value)).toBe('.grand > .parent .child, .other');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('wraps a non-leading complex parent before exact extend output', () => {
|
|
89
|
+
const parent = sel([el('.grand'), co('>'), el('.parent')]);
|
|
90
|
+
const target = sel([el('.prefix'), co(' '), amp({ selectorContainer: { selector: parent } })]);
|
|
91
|
+
const find = sel([el('.prefix'), co(' '), el('.grand'), co('>'), el('.parent')]);
|
|
92
|
+
const result = tryExtendSelector(target, find, el('.other'), false, parent);
|
|
93
|
+
|
|
94
|
+
expect(result.error).toBeUndefined();
|
|
95
|
+
expect(result.value.hoistToRoot).toBeFalsy();
|
|
96
|
+
expect(serialize(result.value)).toBe('.prefix :is(.grand > .parent), .other');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('splices in a non-leading simple parent before exact extend output', () => {
|
|
100
|
+
const parent = el('.parent');
|
|
101
|
+
const target = sel([el('.prefix'), co(' '), amp()]);
|
|
102
|
+
const find = sel([el('.prefix'), co(' '), el('.parent')]);
|
|
103
|
+
const result = tryExtendSelector(target, find, el('.other'), false, parent);
|
|
104
|
+
|
|
105
|
+
expect(result.error).toBeUndefined();
|
|
106
|
+
expect(result.value.hoistToRoot).toBeFalsy();
|
|
107
|
+
expect(serialize(result.value)).toBe('.prefix .parent, .other');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('wraps a simple partial match in :is()', () => {
|
|
111
|
+
const target = sel([el('.a'), co('>'), el('.b')]);
|
|
112
|
+
const result = tryExtendSelector(target, el('.b'), el('.c'), true);
|
|
113
|
+
|
|
114
|
+
expect(result.error).toBeUndefined();
|
|
115
|
+
expect(result.value).not.toBe(target);
|
|
116
|
+
expect(serialize(result.value)).toBe('.a > :is(.b, .c)');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('wraps a compound-local partial match in :is()', () => {
|
|
120
|
+
const target = sel([el('.a'), co('>'), compound([el('.b'), el('.c')])]);
|
|
121
|
+
const result = tryExtendSelector(target, el('.b'), el('.d'), true);
|
|
122
|
+
|
|
123
|
+
expect(result.error).toBeUndefined();
|
|
124
|
+
expect(result.value).not.toBe(target);
|
|
125
|
+
expect(serialize(result.value)).toBe('.a > :is(.b, .d).c');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('wraps a root compound partial match in :is()', () => {
|
|
129
|
+
const target = compound([el('.b'), el('.c')]);
|
|
130
|
+
const result = tryExtendSelector(target, el('.b'), el('.d'), true);
|
|
131
|
+
|
|
132
|
+
expect(result.error).toBeUndefined();
|
|
133
|
+
expect(result.value).not.toBe(target);
|
|
134
|
+
expect(serialize(result.value)).toBe(':is(.b, .d).c');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('wraps a left-side complex partial match in :is()', () => {
|
|
138
|
+
const target = sel([el('.parent'), co('>'), el('.child')]);
|
|
139
|
+
const result = tryExtendSelector(target, el('.parent'), el('.container'), true);
|
|
140
|
+
|
|
141
|
+
expect(result.error).toBeUndefined();
|
|
142
|
+
expect(result.value).not.toBe(target);
|
|
143
|
+
expect(serialize(result.value)).toBe(':is(.parent, .container) > .child');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('wraps a partial match inside a sole :is() selector', () => {
|
|
147
|
+
const target = is(compound([el('.b'), el('.c')]));
|
|
148
|
+
const result = tryExtendSelector(target, el('.b'), el('.d'), true);
|
|
149
|
+
|
|
150
|
+
expect(result.error).toBeUndefined();
|
|
151
|
+
expect(result.value).not.toBe(target);
|
|
152
|
+
expect(serialize(result.value)).toBe(':is(:is(.b, .d).c)');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('appends a full match found inside a selector pseudo arg while in partial mode', () => {
|
|
156
|
+
const target = pseudo({ name: ':where', arg: el('.b') });
|
|
157
|
+
const result = tryExtendSelector(target, el('.b'), el('.d'), true);
|
|
158
|
+
|
|
159
|
+
expect(result.error).toBeUndefined();
|
|
160
|
+
expect(result.value).not.toBe(target);
|
|
161
|
+
expect(serialize(result.value)).toBe(':where(.b, .d)');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('appends into a selector-list arg inside a selector pseudo while in partial mode', () => {
|
|
165
|
+
const target = pseudo({ name: ':where', arg: sellist([el('.x'), el('.b')]) });
|
|
166
|
+
const result = tryExtendSelector(target, el('.b'), el('.d'), true);
|
|
167
|
+
|
|
168
|
+
expect(result.error).toBeUndefined();
|
|
169
|
+
expect(result.value).not.toBe(target);
|
|
170
|
+
expect(serialize(result.value)).toBe(':where(.x, .b, .d)');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('appends a full crossed match into a selector-list arg inside a selector pseudo while in partial mode', () => {
|
|
174
|
+
const parent = el('.a');
|
|
175
|
+
const target = pseudo({
|
|
176
|
+
name: ':where',
|
|
177
|
+
arg: sellist([
|
|
178
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
179
|
+
el('.z')
|
|
180
|
+
])
|
|
181
|
+
});
|
|
182
|
+
const find = compound([el('.a'), el('.x')]);
|
|
183
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
184
|
+
|
|
185
|
+
expect(result.error).toBeUndefined();
|
|
186
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
187
|
+
expect(serialize(result.value)).toBe(':where(.a.x, .z, .other)');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('appends into a sole :is() selector-list arg while in partial mode', () => {
|
|
191
|
+
const target = is(sellist([el('.x'), el('.b')]));
|
|
192
|
+
const result = tryExtendSelector(target, el('.b'), el('.d'), true);
|
|
193
|
+
|
|
194
|
+
expect(result.error).toBeUndefined();
|
|
195
|
+
expect(result.value).not.toBe(target);
|
|
196
|
+
expect(serialize(result.value)).toBe(':is(.x, .b, .d)');
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('appends a full crossed match into a sole :is() selector-list arg while in partial mode', () => {
|
|
200
|
+
const parent = el('.a');
|
|
201
|
+
const target = is(sellist([
|
|
202
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
203
|
+
el('.z')
|
|
204
|
+
]));
|
|
205
|
+
const find = compound([el('.a'), el('.x')]);
|
|
206
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
207
|
+
|
|
208
|
+
expect(result.error).toBeUndefined();
|
|
209
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
210
|
+
expect(serialize(result.value)).toBe(':is(.a.x, .z, .other)');
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('wraps a partial match in a compound with a pseudo-class sibling', () => {
|
|
214
|
+
const target = compound([el('.btn'), pseudo({ name: ':hover' })]);
|
|
215
|
+
const result = tryExtendSelector(target, el('.btn'), el('.primary'), true);
|
|
216
|
+
|
|
217
|
+
expect(result.error).toBeUndefined();
|
|
218
|
+
expect(result.value).not.toBe(target);
|
|
219
|
+
expect(serialize(result.value)).toBe(':is(.btn, .primary):hover');
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('wraps a partial match inside a root selector-list item', () => {
|
|
223
|
+
const target = sellist([el('.x'), compound([el('.b'), el('.c')])]);
|
|
224
|
+
const result = tryExtendSelector(target, el('.b'), el('.d'), true);
|
|
225
|
+
|
|
226
|
+
expect(result.error).toBeUndefined();
|
|
227
|
+
expect(result.value).not.toBe(target);
|
|
228
|
+
expect(serialize(result.value)).toBe('.x, :is(.b, .d).c');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('appends a full match found in a selector-list item while in partial mode', () => {
|
|
232
|
+
const target = sellist([el('.x'), el('.b')]);
|
|
233
|
+
const result = tryExtendSelector(target, el('.b'), el('.d'), true);
|
|
234
|
+
|
|
235
|
+
expect(result.error).toBeUndefined();
|
|
236
|
+
expect(result.value).not.toBe(target);
|
|
237
|
+
expect(serialize(result.value)).toBe('.x, .b, .d');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('hoists and materializes the rest of a selector list when one item crosses an ampersand', () => {
|
|
241
|
+
const parent = el('.parent');
|
|
242
|
+
const target = sellist([
|
|
243
|
+
sel([amp({ selectorContainer: { selector: parent } }), co(' '), el('.child')]),
|
|
244
|
+
sel([amp({ selectorContainer: { selector: parent } }), co(' '), el('.sibling')])
|
|
245
|
+
]);
|
|
246
|
+
const find = sel([el('.parent'), co(' '), el('.child')]);
|
|
247
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
248
|
+
|
|
249
|
+
expect(result.error).toBeUndefined();
|
|
250
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
251
|
+
expect(serialize(result.value)).toBe('.parent .child, .parent .sibling, .other');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('extends within the own part of a leading ampersand when given a parent', () => {
|
|
255
|
+
const parent = el('.parent');
|
|
256
|
+
const target = sel([amp(), co(' '), el('.child')]);
|
|
257
|
+
const result = tryExtendSelector(target, el('.child'), el('.other'), true, parent);
|
|
258
|
+
|
|
259
|
+
expect(result.error).toBeUndefined();
|
|
260
|
+
expect(result.value).not.toBe(target);
|
|
261
|
+
expect(result.value.hoistToRoot).toBeFalsy();
|
|
262
|
+
expect(serialize(result.value)).toBe('& :is(.child, .other)');
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('does not extend when only the parent side would match across a leading ampersand', () => {
|
|
266
|
+
const parent = el('.parent');
|
|
267
|
+
const target = sel([amp(), co(' '), el('.child')]);
|
|
268
|
+
const result = tryExtendSelector(target, el('.parent'), el('.other'), true, parent);
|
|
269
|
+
|
|
270
|
+
expect(result.value).toBe(target);
|
|
271
|
+
expect(result.error?.type).toBe(ExtendErrorType.NOT_FOUND);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('replaces a crossed leading ampersand with the parent and hoists on partial rewrite', () => {
|
|
275
|
+
const parent = el('.parent');
|
|
276
|
+
const target = sel([amp(), co(' '), el('.child')]);
|
|
277
|
+
const find = sel([el('.parent'), co(' '), el('.child')]);
|
|
278
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
279
|
+
|
|
280
|
+
expect(result.error).toBeUndefined();
|
|
281
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
282
|
+
expect(serialize(result.value)).toBe('.parent .child, .other');
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('materializes an implicit parent boundary and hoists on partial rewrite', () => {
|
|
286
|
+
const parent = el('.parent');
|
|
287
|
+
const target = el('.child');
|
|
288
|
+
const find = sel([el('.parent'), co(' '), el('.child')]);
|
|
289
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
290
|
+
|
|
291
|
+
expect(result.error).toBeUndefined();
|
|
292
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
293
|
+
expect(serialize(result.value)).toBe('.parent .child, .other');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('materializes a crossed explicit ampersand on hoist even without a parent argument', () => {
|
|
297
|
+
const resolvedParent = el('.parent');
|
|
298
|
+
const target = sel([amp({ selectorContainer: { selector: resolvedParent } }), co(' '), el('.child')]);
|
|
299
|
+
const find = sel([el('.parent'), co(' '), el('.child')]);
|
|
300
|
+
const result = tryExtendSelector(target, find, el('.other'), true);
|
|
301
|
+
|
|
302
|
+
expect(result.error).toBeUndefined();
|
|
303
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
304
|
+
expect(serialize(result.value)).toBe('.parent .child, .other');
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('wraps a selector-list parent when replacing a crossed leading ampersand', () => {
|
|
308
|
+
const parent = sellist([el('div'), el('span')]);
|
|
309
|
+
const target = sel([amp(), co(' '), el('.child')]);
|
|
310
|
+
const find = sel([el('span'), co(' '), el('.child')]);
|
|
311
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
312
|
+
|
|
313
|
+
expect(result.error).toBeUndefined();
|
|
314
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
315
|
+
expect(serialize(result.value)).toBe(':is(div, span) .child, .other');
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('splices in a complex parent directly when replacing a crossed leading ampersand', () => {
|
|
319
|
+
const parent = sel([el('.grand'), co('>'), el('.parent')]);
|
|
320
|
+
const target = sel([amp(), co(' '), el('.child')]);
|
|
321
|
+
const find = sel([el('.grand'), co('>'), el('.parent'), co(' '), el('.child')]);
|
|
322
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
323
|
+
|
|
324
|
+
expect(result.error).toBeUndefined();
|
|
325
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
326
|
+
expect(serialize(result.value)).toBe('.grand > .parent .child, .other');
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it('splices in a simple parent directly when replacing a crossed non-leading ampersand', () => {
|
|
330
|
+
const parent = el('.parent');
|
|
331
|
+
const target = sel([el('.prefix'), co(' '), amp()]);
|
|
332
|
+
const find = sel([el('.prefix'), co(' '), el('.parent')]);
|
|
333
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
334
|
+
|
|
335
|
+
expect(result.error).toBeUndefined();
|
|
336
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
337
|
+
expect(serialize(result.value)).toBe('.prefix .parent, .other');
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('wraps a complex parent when replacing a crossed non-leading ampersand', () => {
|
|
341
|
+
const parent = sel([el('.grand'), co('>'), el('.parent')]);
|
|
342
|
+
const target = sel([el('.prefix'), co(' '), amp({ selectorContainer: { selector: parent } })]);
|
|
343
|
+
const find = sel([el('.prefix'), co(' '), el('.grand'), co('>'), el('.parent')]);
|
|
344
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
345
|
+
|
|
346
|
+
expect(result.error).toBeUndefined();
|
|
347
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
348
|
+
expect(serialize(result.value)).toBe('.prefix :is(.grand > .parent), .other');
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('resolves only the crossed ampersand inside a partial matched span', () => {
|
|
352
|
+
const parent = el('.parent');
|
|
353
|
+
const target = sel([amp({ selectorContainer: { selector: parent } }), co(' '), el('.child'), co(' '), amp({ selectorContainer: { selector: parent } })]);
|
|
354
|
+
const find = sel([el('.parent'), co(' '), el('.child')]);
|
|
355
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
356
|
+
|
|
357
|
+
expect(result.error).toBeUndefined();
|
|
358
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
359
|
+
expect(serialize(result.value)).toBe(':is(.parent .child, .other) .parent');
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('groups only the matched crossed seam when multiple authored ampersands exist', () => {
|
|
363
|
+
const parent = el('.a');
|
|
364
|
+
const target = sel([
|
|
365
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
366
|
+
co(' '),
|
|
367
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')])
|
|
368
|
+
]);
|
|
369
|
+
const find = compound([el('.a'), el('.x')]);
|
|
370
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
371
|
+
|
|
372
|
+
expect(result.error).toBeUndefined();
|
|
373
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
374
|
+
expect(serialize(result.value)).toBe(':is(.a.x, .other) .a.x');
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('creates a plain alternative when an exact match crosses multiple authored seams', () => {
|
|
378
|
+
const parent = el('.a');
|
|
379
|
+
const target = sel([
|
|
380
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
381
|
+
co('+'),
|
|
382
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.y')])
|
|
383
|
+
]);
|
|
384
|
+
const find = sel([
|
|
385
|
+
compound([el('.a'), el('.x')]),
|
|
386
|
+
co('+'),
|
|
387
|
+
compound([el('.a'), el('.y')])
|
|
388
|
+
]);
|
|
389
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
390
|
+
|
|
391
|
+
expect(result.error).toBeUndefined();
|
|
392
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
393
|
+
expect(serialize(result.value)).toBe('.a.x + .a.y, .other');
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('groups a crossed seam as one component inside a larger root compound', () => {
|
|
397
|
+
const parent = el('.a');
|
|
398
|
+
const target = compound([
|
|
399
|
+
amp({ selectorContainer: { selector: parent } }),
|
|
400
|
+
el('.x'),
|
|
401
|
+
el('.y')
|
|
402
|
+
]);
|
|
403
|
+
const find = compound([el('.a'), el('.x')]);
|
|
404
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
405
|
+
|
|
406
|
+
expect(result.error).toBeUndefined();
|
|
407
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
408
|
+
expect(serialize(result.value)).toBe(':is(.a.x, .other).y');
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('does not over-wrap unmatched tail compound members in a crossed ordered span', () => {
|
|
412
|
+
const parent = el('.a');
|
|
413
|
+
const target = sel([
|
|
414
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
415
|
+
co('>'),
|
|
416
|
+
compound([el('.y'), el('.w')])
|
|
417
|
+
]);
|
|
418
|
+
const find = sel([
|
|
419
|
+
compound([el('.a'), el('.x')]),
|
|
420
|
+
co('>'),
|
|
421
|
+
el('.y')
|
|
422
|
+
]);
|
|
423
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
424
|
+
|
|
425
|
+
expect(result.error).toBeUndefined();
|
|
426
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
427
|
+
expect(serialize(result.value)).toBe(':is(.a.x > .y, .other).w');
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it('does not over-wrap an unmatched tail when a partial ordered span crosses multiple authored seams', () => {
|
|
431
|
+
const parent = el('.a');
|
|
432
|
+
const target = sel([
|
|
433
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
434
|
+
co('+'),
|
|
435
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.y'), el('.z')])
|
|
436
|
+
]);
|
|
437
|
+
const find = sel([
|
|
438
|
+
compound([el('.a'), el('.x')]),
|
|
439
|
+
co('+'),
|
|
440
|
+
compound([el('.a'), el('.y')])
|
|
441
|
+
]);
|
|
442
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
443
|
+
|
|
444
|
+
expect(result.error).toBeUndefined();
|
|
445
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
446
|
+
expect(serialize(result.value)).toBe(':is(.a.x + .a.y, .other).z');
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('rewrites a crossed ordered span inside one selector-list item without over-wrapping sibling items', () => {
|
|
450
|
+
const parent = el('.a');
|
|
451
|
+
const target = sellist([
|
|
452
|
+
sel([
|
|
453
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
454
|
+
co('>'),
|
|
455
|
+
compound([el('.y'), el('.w')])
|
|
456
|
+
]),
|
|
457
|
+
el('.z')
|
|
458
|
+
]);
|
|
459
|
+
const find = sel([
|
|
460
|
+
compound([el('.a'), el('.x')]),
|
|
461
|
+
co('>'),
|
|
462
|
+
el('.y')
|
|
463
|
+
]);
|
|
464
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
465
|
+
|
|
466
|
+
expect(result.error).toBeUndefined();
|
|
467
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
468
|
+
expect(serialize(result.value)).toBe(':is(.a.x > .y, .other).w, .z');
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
it('rewrites a crossed ordered span inside a selector pseudo arg without over-wrapping the tail', () => {
|
|
472
|
+
const parent = el('.a');
|
|
473
|
+
const target = pseudo({
|
|
474
|
+
name: ':where',
|
|
475
|
+
arg: sel([
|
|
476
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
477
|
+
co('>'),
|
|
478
|
+
compound([el('.y'), el('.w')])
|
|
479
|
+
])
|
|
480
|
+
});
|
|
481
|
+
const find = sel([
|
|
482
|
+
compound([el('.a'), el('.x')]),
|
|
483
|
+
co('>'),
|
|
484
|
+
el('.y')
|
|
485
|
+
]);
|
|
486
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
487
|
+
|
|
488
|
+
expect(result.error).toBeUndefined();
|
|
489
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
490
|
+
expect(serialize(result.value)).toBe(':where(:is(.a.x > .y, .other).w)');
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it('rewrites a crossed ordered span inside one nested :is() alternative without over-wrapping siblings', () => {
|
|
494
|
+
const parent = el('.a');
|
|
495
|
+
const target = is(sellist([
|
|
496
|
+
sel([
|
|
497
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
498
|
+
co('>'),
|
|
499
|
+
compound([el('.y'), el('.w')])
|
|
500
|
+
]),
|
|
501
|
+
el('.z')
|
|
502
|
+
]));
|
|
503
|
+
const find = sel([
|
|
504
|
+
compound([el('.a'), el('.x')]),
|
|
505
|
+
co('>'),
|
|
506
|
+
el('.y')
|
|
507
|
+
]);
|
|
508
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
509
|
+
|
|
510
|
+
expect(result.error).toBeUndefined();
|
|
511
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
512
|
+
expect(serialize(result.value)).toBe(':is(:is(.a.x > .y, .other).w, .z)');
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
it('rewrites a crossed compound seam inside one nested :is() alternative without over-wrapping siblings', () => {
|
|
516
|
+
const parent = el('.a');
|
|
517
|
+
const target = is(sellist([
|
|
518
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x'), el('.y')]),
|
|
519
|
+
el('.z')
|
|
520
|
+
]));
|
|
521
|
+
const find = compound([el('.a'), el('.x')]);
|
|
522
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
523
|
+
|
|
524
|
+
expect(result.error).toBeUndefined();
|
|
525
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
526
|
+
expect(serialize(result.value)).toBe(':is(:is(.a.x, .other).y, .z)');
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it('rewrites a crossed compound seam inside a non-:is() selector pseudo arg without over-wrapping sibling alternatives', () => {
|
|
530
|
+
const parent = el('.a');
|
|
531
|
+
const target = pseudo({
|
|
532
|
+
name: ':where',
|
|
533
|
+
arg: sellist([
|
|
534
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x'), el('.y')]),
|
|
535
|
+
el('.z')
|
|
536
|
+
])
|
|
537
|
+
});
|
|
538
|
+
const find = compound([el('.a'), el('.x')]);
|
|
539
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
540
|
+
|
|
541
|
+
expect(result.error).toBeUndefined();
|
|
542
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
543
|
+
expect(serialize(result.value)).toBe(':where(:is(.a.x, .other).y, .z)');
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it('rewrites a crossed ordered span inside a non-:is() selector pseudo arg without over-wrapping sibling alternatives', () => {
|
|
547
|
+
const parent = el('.a');
|
|
548
|
+
const target = pseudo({
|
|
549
|
+
name: ':where',
|
|
550
|
+
arg: sellist([
|
|
551
|
+
sel([
|
|
552
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
553
|
+
co('>'),
|
|
554
|
+
compound([el('.y'), el('.w')])
|
|
555
|
+
]),
|
|
556
|
+
el('.z')
|
|
557
|
+
])
|
|
558
|
+
});
|
|
559
|
+
const find = sel([
|
|
560
|
+
compound([el('.a'), el('.x')]),
|
|
561
|
+
co('>'),
|
|
562
|
+
el('.y')
|
|
563
|
+
]);
|
|
564
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
565
|
+
|
|
566
|
+
expect(result.error).toBeUndefined();
|
|
567
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
568
|
+
expect(serialize(result.value)).toBe(':where(:is(.a.x > .y, .other).w, .z)');
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
it('materializes remaining ampersands with the normal wrapping rules after hoisting', () => {
|
|
572
|
+
const parent = sel([el('.grand'), co('>'), el('.parent')]);
|
|
573
|
+
const target = sel([amp({ selectorContainer: { selector: parent } }), co(' '), el('.prefix'), co(' '), amp({ selectorContainer: { selector: parent } }), co(' '), el('.child')]);
|
|
574
|
+
const find = sel([el('.grand'), co('>'), el('.parent'), co(' '), el('.child')]);
|
|
575
|
+
const result = tryExtendSelector(target, find, el('.other'), true, parent);
|
|
576
|
+
|
|
577
|
+
expect(result.error).toBeUndefined();
|
|
578
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
579
|
+
expect(serialize(result.value)).toBe('.grand > .parent .prefix :is(.grand > .parent .child, .other)');
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it('does not extend when combinators differ (space vs +)', () => {
|
|
583
|
+
const target = sel([el('.ext8'), co(' '), el('.ext9')]);
|
|
584
|
+
const find = sel([el('.ext8'), co('+'), el('.ext9')]);
|
|
585
|
+
const result = tryExtendSelector(target, find, el('.zap'), true);
|
|
586
|
+
|
|
587
|
+
expect(result.value).toBe(target);
|
|
588
|
+
expect(result.error?.type).toBe(ExtendErrorType.NOT_FOUND);
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
it('does not extend a selector-list item when combinators differ', () => {
|
|
592
|
+
const target = sellist([
|
|
593
|
+
sel([el('.ext8'), co(' '), el('.ext9')]),
|
|
594
|
+
el('.buu')
|
|
595
|
+
]);
|
|
596
|
+
const find = sel([el('.ext8'), co('>'), el('.ext9')]);
|
|
597
|
+
const result = tryExtendSelector(target, find, el('.zoo'), true);
|
|
598
|
+
|
|
599
|
+
expect(result.value).toBe(target);
|
|
600
|
+
expect(result.error?.type).toBe(ExtendErrorType.NOT_FOUND);
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
it('does not extend when the match exists only inside a resolved ampersand', () => {
|
|
604
|
+
const target = compound([
|
|
605
|
+
amp({ selectorContainer: { selector: el('.clearfix') } }),
|
|
606
|
+
pseudo({ name: ':after' })
|
|
607
|
+
]);
|
|
608
|
+
const result = tryExtendSelector(target, el('.clearfix'), el('.foo'), true);
|
|
609
|
+
|
|
610
|
+
expect(result.value).toBe(target);
|
|
611
|
+
expect(result.error?.type).toBe(ExtendErrorType.NOT_FOUND);
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
it('returns ELEMENT_CONFLICT when a partial compound rewrite would introduce a different element', () => {
|
|
615
|
+
const target = compound([el('a'), el('.info')]);
|
|
616
|
+
const result = tryExtendSelector(target, el('.info'), compound([el('div'), el('.foo')]), true);
|
|
617
|
+
|
|
618
|
+
expect(result.value).toBe(target);
|
|
619
|
+
expect(result.error?.type).toBe(ExtendErrorType.ELEMENT_CONFLICT);
|
|
620
|
+
expect(serialize(result.value)).toBe('a.info');
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
it('returns ID_CONFLICT when a partial compound rewrite would introduce a different id', () => {
|
|
624
|
+
const target = compound([el('#first'), el('.class')]);
|
|
625
|
+
const result = tryExtendSelector(target, el('.class'), compound([el('#second'), el('.other')]), true);
|
|
626
|
+
|
|
627
|
+
expect(result.value).toBe(target);
|
|
628
|
+
expect(result.error?.type).toBe(ExtendErrorType.ID_CONFLICT);
|
|
629
|
+
expect(serialize(result.value)).toBe('#first.class');
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
it('allows a partial compound rewrite when the extension uses the same element', () => {
|
|
633
|
+
const target = compound([el('div'), el('.a')]);
|
|
634
|
+
const result = tryExtendSelector(target, el('.a'), compound([el('div'), el('.b')]), true);
|
|
635
|
+
|
|
636
|
+
expect(result.error).toBeUndefined();
|
|
637
|
+
expect(result.value).not.toBe(target);
|
|
638
|
+
expect(serialize(result.value)).toBe('div:is(.a, .b)');
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
it('allows a partial compound rewrite when the extension uses the same id', () => {
|
|
642
|
+
const target = compound([el('#foo'), el('.class')]);
|
|
643
|
+
const result = tryExtendSelector(target, el('.class'), compound([el('#foo'), el('.other')]), true);
|
|
644
|
+
|
|
645
|
+
expect(result.error).toBeUndefined();
|
|
646
|
+
expect(result.value).not.toBe(target);
|
|
647
|
+
expect(serialize(result.value)).toBe('#foo:is(.class, .other)');
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
it('allows a different element when it stays in a different complex-selector position', () => {
|
|
651
|
+
const target = sel([el('a'), co('>'), el('.class')]);
|
|
652
|
+
const result = tryExtendSelector(target, el('.class'), compound([el('span'), el('.other')]), true);
|
|
653
|
+
|
|
654
|
+
expect(result.error).toBeUndefined();
|
|
655
|
+
expect(result.value).not.toBe(target);
|
|
656
|
+
expect(serialize(result.value)).toBe('a > :is(.class, span.other)');
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
it('wraps the full matched segment when a partial match spans a combinator', () => {
|
|
660
|
+
const target = sel([
|
|
661
|
+
el('div'),
|
|
662
|
+
co('+'),
|
|
663
|
+
compound([el('.a'), el('.c'), el('.b')]),
|
|
664
|
+
co('>'),
|
|
665
|
+
compound([el('.y'), el('.x')])
|
|
666
|
+
]);
|
|
667
|
+
const find = sel([
|
|
668
|
+
compound([el('.a'), el('.b')]),
|
|
669
|
+
co('>'),
|
|
670
|
+
el('.x')
|
|
671
|
+
]);
|
|
672
|
+
const result = tryExtendSelector(target, find, el('.q'), true);
|
|
673
|
+
|
|
674
|
+
expect(result.error).toBeUndefined();
|
|
675
|
+
expect(result.value).not.toBe(target);
|
|
676
|
+
expect(serialize(result.value)).toBe('div + :is(.a.c.b > .y.x, .q)');
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it('wraps only the matched compound subspan inside a larger root compound', () => {
|
|
680
|
+
const target = compound([el('.a'), el('.b'), el('.c')]);
|
|
681
|
+
const find = compound([el('.a'), el('.b')]);
|
|
682
|
+
const result = tryExtendSelector(target, find, el('.q'), true);
|
|
683
|
+
|
|
684
|
+
expect(result.error).toBeUndefined();
|
|
685
|
+
expect(result.value).not.toBe(target);
|
|
686
|
+
expect(serialize(result.value)).toBe(':is(.a.b, .q).c');
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
it('groups non-sequential matched compound members in :is() and leaves the gap outside', () => {
|
|
690
|
+
const target = compound([el('.b'), el('.a'), el('.x')]);
|
|
691
|
+
const find = compound([el('.b'), el('.x')]);
|
|
692
|
+
const result = tryExtendSelector(target, find, el('.q'), true);
|
|
693
|
+
|
|
694
|
+
expect(result.error).toBeUndefined();
|
|
695
|
+
expect(result.value).not.toBe(target);
|
|
696
|
+
expect(serialize(result.value)).toBe(':is(.b.x, .q).a');
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
it('wraps a partial match inside one root :is() alternative only', () => {
|
|
700
|
+
const target = is(sellist([
|
|
701
|
+
sel([el('.foo'), co(' '), el('.bar')]),
|
|
702
|
+
el('.baz')
|
|
703
|
+
]));
|
|
704
|
+
const result = tryExtendSelector(target, el('.bar'), el('.q'), true);
|
|
705
|
+
|
|
706
|
+
expect(result.error).toBeUndefined();
|
|
707
|
+
expect(result.value).not.toBe(target);
|
|
708
|
+
expect(serialize(result.value)).toBe(':is(.foo :is(.bar, .q), .baz)');
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
it('wraps a partial match inside one nested :is() alternative within a compound', () => {
|
|
712
|
+
const target = compound([
|
|
713
|
+
el('.outer'),
|
|
714
|
+
is(sellist([compound([el('.a'), el('.b')]), el('.x')])),
|
|
715
|
+
el('.tail')
|
|
716
|
+
]);
|
|
717
|
+
const result = tryExtendSelector(target, el('.a'), el('.q'), true);
|
|
718
|
+
|
|
719
|
+
expect(result.error).toBeUndefined();
|
|
720
|
+
expect(result.value).not.toBe(target);
|
|
721
|
+
expect(serialize(result.value)).toBe('.outer:is(:is(.a, .q).b, .x).tail');
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
it('appends into a nested :is() list within a compound when the inner match is full', () => {
|
|
725
|
+
const target = compound([
|
|
726
|
+
el('.a'),
|
|
727
|
+
is(sellist([el('.b'), el('.c')])),
|
|
728
|
+
el('.d')
|
|
729
|
+
]);
|
|
730
|
+
const result = tryExtendSelector(target, el('.b'), el('.q'), true);
|
|
731
|
+
|
|
732
|
+
expect(result.error).toBeUndefined();
|
|
733
|
+
expect(result.value).not.toBe(target);
|
|
734
|
+
expect(serialize(result.value)).toBe('.a:is(.b, .c, .q).d');
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
it('pulls an outer compound match into a nested :is() branch when they refer to the same component', () => {
|
|
738
|
+
const target = sel([
|
|
739
|
+
el('qux'),
|
|
740
|
+
co('>'),
|
|
741
|
+
compound([
|
|
742
|
+
el('.a'),
|
|
743
|
+
is(sel([el('div'), co('>'), el('.b')])),
|
|
744
|
+
el('.c')
|
|
745
|
+
]),
|
|
746
|
+
co('>'),
|
|
747
|
+
el('qux')
|
|
748
|
+
]);
|
|
749
|
+
const result = tryExtendSelector(target, compound([el('.a'), el('.b')]), el('.foo'), true);
|
|
750
|
+
|
|
751
|
+
expect(result.error).toBeUndefined();
|
|
752
|
+
expect(result.value).not.toBe(target);
|
|
753
|
+
expect(serialize(result.value)).toBe('qux > :is(div > :is(.a.b, .foo)).c > qux');
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
it('can pull a target from a nested :is() branch into the surrounding compound component', () => {
|
|
757
|
+
const target = compound([
|
|
758
|
+
el('.a'),
|
|
759
|
+
is(sel([el('div'), co('>'), el('.c')])),
|
|
760
|
+
el('.b')
|
|
761
|
+
]);
|
|
762
|
+
const result = tryExtendSelector(target, sel([el('div'), co('>'), el('.c')]), el('.foo'), true);
|
|
763
|
+
|
|
764
|
+
expect(result.error).toBeUndefined();
|
|
765
|
+
expect(result.value).not.toBe(target);
|
|
766
|
+
expect(serialize(result.value)).toBe('.a:is(div > .c, .foo).b');
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
it('creates a plain alternative when a full match crosses out of a nested :is() branch', () => {
|
|
770
|
+
const target = compound([
|
|
771
|
+
is(sellist([el('.a'), el('.b')])),
|
|
772
|
+
el('.c')
|
|
773
|
+
]);
|
|
774
|
+
const result = tryExtendSelector(target, compound([el('.b'), el('.c')]), el('.d'), true);
|
|
775
|
+
|
|
776
|
+
expect(result.error).toBeUndefined();
|
|
777
|
+
expect(serialize(result.value)).toBe(':is(.a, .b).c, .d');
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
it('preserves nested :is() structure when the partial match stays within the same inner group', () => {
|
|
781
|
+
const target = compound([
|
|
782
|
+
is(sellist([el('.g'), compound([el('.i'), el('.j')])])),
|
|
783
|
+
el('.h')
|
|
784
|
+
]);
|
|
785
|
+
const result = tryExtendSelector(target, el('.i'), el('.k'), true);
|
|
786
|
+
|
|
787
|
+
expect(result.error).toBeUndefined();
|
|
788
|
+
expect(serialize(result.value)).toBe(':is(.g, :is(.i, .k).j).h');
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
it('appends into a nested :is() list when a full compound match stays within that inner group', () => {
|
|
792
|
+
const target = compound([
|
|
793
|
+
is(sellist([el('.g'), compound([el('.i'), el('.j')])])),
|
|
794
|
+
el('.h')
|
|
795
|
+
]);
|
|
796
|
+
const result = tryExtendSelector(target, compound([el('.i'), el('.j')]), el('.k'), true);
|
|
797
|
+
|
|
798
|
+
expect(result.error).toBeUndefined();
|
|
799
|
+
expect(serialize(result.value)).toBe(':is(.g, .i.j, .k).h');
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
it('appends a full crossed match into a nested :is() list within a compound', () => {
|
|
803
|
+
const parent = el('.a');
|
|
804
|
+
const target = compound([
|
|
805
|
+
is(sellist([
|
|
806
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
807
|
+
el('.z')
|
|
808
|
+
])),
|
|
809
|
+
el('.h')
|
|
810
|
+
]);
|
|
811
|
+
const find = compound([el('.a'), el('.x')]);
|
|
812
|
+
const result = tryExtendSelector(target, find, el('.k'), true, parent);
|
|
813
|
+
|
|
814
|
+
expect(result.error).toBeUndefined();
|
|
815
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
816
|
+
expect(serialize(result.value)).toBe(':is(.a.x, .z, .k).h');
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
it('appends a full crossed ordered span into a nested :is() list within a compound', () => {
|
|
820
|
+
const parent = el('.a');
|
|
821
|
+
const target = compound([
|
|
822
|
+
is(sellist([
|
|
823
|
+
sel([
|
|
824
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
825
|
+
co('>'),
|
|
826
|
+
el('.y')
|
|
827
|
+
]),
|
|
828
|
+
el('.z')
|
|
829
|
+
])),
|
|
830
|
+
el('.h')
|
|
831
|
+
]);
|
|
832
|
+
const find = sel([
|
|
833
|
+
compound([el('.a'), el('.x')]),
|
|
834
|
+
co('>'),
|
|
835
|
+
el('.y')
|
|
836
|
+
]);
|
|
837
|
+
const result = tryExtendSelector(target, find, el('.k'), true, parent);
|
|
838
|
+
|
|
839
|
+
expect(result.error).toBeUndefined();
|
|
840
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
841
|
+
expect(serialize(result.value)).toBe(':is(.a.x > .y, .z, .k).h');
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
it('appends a full crossed ordered span into a non-:is() selector pseudo arg within a compound', () => {
|
|
845
|
+
const parent = el('.a');
|
|
846
|
+
const target = compound([
|
|
847
|
+
pseudo({
|
|
848
|
+
name: ':where',
|
|
849
|
+
arg: sellist([
|
|
850
|
+
sel([
|
|
851
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
852
|
+
co('>'),
|
|
853
|
+
el('.y')
|
|
854
|
+
]),
|
|
855
|
+
el('.z')
|
|
856
|
+
])
|
|
857
|
+
}),
|
|
858
|
+
el('.h')
|
|
859
|
+
]);
|
|
860
|
+
const find = sel([
|
|
861
|
+
compound([el('.a'), el('.x')]),
|
|
862
|
+
co('>'),
|
|
863
|
+
el('.y')
|
|
864
|
+
]);
|
|
865
|
+
const result = tryExtendSelector(target, find, el('.k'), true, parent);
|
|
866
|
+
|
|
867
|
+
expect(result.error).toBeUndefined();
|
|
868
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
869
|
+
expect(serialize(result.value)).toBe(':where(.a.x > .y, .z, .k).h');
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
it('appends a full crossed compound match into a non-:is() selector pseudo arg within a compound', () => {
|
|
873
|
+
const parent = el('.a');
|
|
874
|
+
const target = compound([
|
|
875
|
+
pseudo({
|
|
876
|
+
name: ':where',
|
|
877
|
+
arg: sellist([
|
|
878
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
879
|
+
el('.z')
|
|
880
|
+
])
|
|
881
|
+
}),
|
|
882
|
+
el('.h')
|
|
883
|
+
]);
|
|
884
|
+
const find = compound([el('.a'), el('.x')]);
|
|
885
|
+
const result = tryExtendSelector(target, find, el('.k'), true, parent);
|
|
886
|
+
|
|
887
|
+
expect(result.error).toBeUndefined();
|
|
888
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
889
|
+
expect(serialize(result.value)).toBe(':where(.a.x, .z, .k).h');
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
it('appends a full crossed ordered span into a non-:is() selector pseudo arg within a complex selector', () => {
|
|
893
|
+
const parent = el('.a');
|
|
894
|
+
const target = sel([
|
|
895
|
+
el('div'),
|
|
896
|
+
co('>'),
|
|
897
|
+
pseudo({
|
|
898
|
+
name: ':where',
|
|
899
|
+
arg: sellist([
|
|
900
|
+
sel([
|
|
901
|
+
compound([amp({ selectorContainer: { selector: parent } }), el('.x')]),
|
|
902
|
+
co('>'),
|
|
903
|
+
el('.y')
|
|
904
|
+
]),
|
|
905
|
+
el('.z')
|
|
906
|
+
])
|
|
907
|
+
})
|
|
908
|
+
]);
|
|
909
|
+
const find = sel([
|
|
910
|
+
compound([el('.a'), el('.x')]),
|
|
911
|
+
co('>'),
|
|
912
|
+
el('.y')
|
|
913
|
+
]);
|
|
914
|
+
const result = tryExtendSelector(target, find, el('.k'), true, parent);
|
|
915
|
+
|
|
916
|
+
expect(result.error).toBeUndefined();
|
|
917
|
+
expect(result.value.hoistToRoot).toBe(true);
|
|
918
|
+
expect(serialize(result.value)).toBe('div > :where(.a.x > .y, .z, .k)');
|
|
919
|
+
});
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
describe('extend-exact: SelectorList target with SelectorList parent (cross-nesting)', () => {
|
|
923
|
+
// Models:
|
|
924
|
+
// .replace.replace, .c.replace + .replace { .replace, .c { prop: ... } }
|
|
925
|
+
// .rep_ace:extend(.replace.replace .replace) {}
|
|
926
|
+
//
|
|
927
|
+
// Expected: :is(.replace.replace, .c.replace + .replace) :is(.replace, .c), .rep_ace
|
|
928
|
+
const parent = () => sellist([
|
|
929
|
+
compound([el('.replace'), el('.replace')]),
|
|
930
|
+
sel([compound([el('.c'), el('.replace')]), co('+'), compound([el('.replace')])])
|
|
931
|
+
]);
|
|
932
|
+
const target = () => sellist([el('.replace'), el('.c')]);
|
|
933
|
+
const find = () => sel([compound([el('.replace'), el('.replace')]), co(' '), el('.replace')]);
|
|
934
|
+
|
|
935
|
+
it('produces :is(outer) :is(inner), .rep_ace for exact extend crossing nested SelectorList', () => {
|
|
936
|
+
const result = tryExtendSelector(target(), find(), el('.rep_ace'), false, parent());
|
|
937
|
+
|
|
938
|
+
expect(result.error).toBeUndefined();
|
|
939
|
+
expect(serialize(result.value)).toBe(':is(.replace.replace, .c.replace + .replace) :is(.replace, .c), .rep_ace');
|
|
940
|
+
});
|
|
941
|
+
});
|