@jesscss/core 2.0.0-alpha.1
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/LICENSE +21 -0
- package/README.md +9 -0
- package/lib/context.d.ts +352 -0
- package/lib/context.d.ts.map +1 -0
- package/lib/context.js +636 -0
- package/lib/context.js.map +1 -0
- package/lib/conversions.d.ts +73 -0
- package/lib/conversions.d.ts.map +1 -0
- package/lib/conversions.js +253 -0
- package/lib/conversions.js.map +1 -0
- package/lib/debug-log.d.ts +2 -0
- package/lib/debug-log.d.ts.map +1 -0
- package/lib/debug-log.js +27 -0
- package/lib/debug-log.js.map +1 -0
- package/lib/define-function.d.ts +587 -0
- package/lib/define-function.d.ts.map +1 -0
- package/lib/define-function.js +726 -0
- package/lib/define-function.js.map +1 -0
- package/lib/deprecation.d.ts +34 -0
- package/lib/deprecation.d.ts.map +1 -0
- package/lib/deprecation.js +57 -0
- package/lib/deprecation.js.map +1 -0
- package/lib/index.d.ts +22 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +23 -0
- package/lib/index.js.map +1 -0
- package/lib/jess-error.d.ts +343 -0
- package/lib/jess-error.d.ts.map +1 -0
- package/lib/jess-error.js +508 -0
- package/lib/jess-error.js.map +1 -0
- package/lib/logger/deprecation-processing.d.ts +41 -0
- package/lib/logger/deprecation-processing.d.ts.map +1 -0
- package/lib/logger/deprecation-processing.js +81 -0
- package/lib/logger/deprecation-processing.js.map +1 -0
- package/lib/logger.d.ts +10 -0
- package/lib/logger.d.ts.map +1 -0
- package/lib/logger.js +20 -0
- package/lib/logger.js.map +1 -0
- package/lib/plugin.d.ts +94 -0
- package/lib/plugin.d.ts.map +1 -0
- package/lib/plugin.js +174 -0
- package/lib/plugin.js.map +1 -0
- package/lib/tree/ampersand.d.ts +94 -0
- package/lib/tree/ampersand.d.ts.map +1 -0
- package/lib/tree/ampersand.js +269 -0
- package/lib/tree/ampersand.js.map +1 -0
- package/lib/tree/any.d.ts +58 -0
- package/lib/tree/any.d.ts.map +1 -0
- package/lib/tree/any.js +101 -0
- package/lib/tree/any.js.map +1 -0
- package/lib/tree/at-rule.d.ts +53 -0
- package/lib/tree/at-rule.d.ts.map +1 -0
- package/lib/tree/at-rule.js +503 -0
- package/lib/tree/at-rule.js.map +1 -0
- package/lib/tree/block.d.ts +22 -0
- package/lib/tree/block.d.ts.map +1 -0
- package/lib/tree/block.js +24 -0
- package/lib/tree/block.js.map +1 -0
- package/lib/tree/bool.d.ts +17 -0
- package/lib/tree/bool.d.ts.map +1 -0
- package/lib/tree/bool.js +24 -0
- package/lib/tree/bool.js.map +1 -0
- package/lib/tree/call.d.ts +66 -0
- package/lib/tree/call.d.ts.map +1 -0
- package/lib/tree/call.js +306 -0
- package/lib/tree/call.js.map +1 -0
- package/lib/tree/collection.d.ts +30 -0
- package/lib/tree/collection.d.ts.map +1 -0
- package/lib/tree/collection.js +37 -0
- package/lib/tree/collection.js.map +1 -0
- package/lib/tree/color.d.ts +101 -0
- package/lib/tree/color.d.ts.map +1 -0
- package/lib/tree/color.js +513 -0
- package/lib/tree/color.js.map +1 -0
- package/lib/tree/combinator.d.ts +12 -0
- package/lib/tree/combinator.d.ts.map +1 -0
- package/lib/tree/combinator.js +8 -0
- package/lib/tree/combinator.js.map +1 -0
- package/lib/tree/comment.d.ts +20 -0
- package/lib/tree/comment.d.ts.map +1 -0
- package/lib/tree/comment.js +18 -0
- package/lib/tree/comment.js.map +1 -0
- package/lib/tree/condition.d.ts +31 -0
- package/lib/tree/condition.d.ts.map +1 -0
- package/lib/tree/condition.js +103 -0
- package/lib/tree/condition.js.map +1 -0
- package/lib/tree/control.d.ts +104 -0
- package/lib/tree/control.d.ts.map +1 -0
- package/lib/tree/control.js +430 -0
- package/lib/tree/control.js.map +1 -0
- package/lib/tree/declaration-custom.d.ts +18 -0
- package/lib/tree/declaration-custom.d.ts.map +1 -0
- package/lib/tree/declaration-custom.js +24 -0
- package/lib/tree/declaration-custom.js.map +1 -0
- package/lib/tree/declaration-var.d.ts +36 -0
- package/lib/tree/declaration-var.d.ts.map +1 -0
- package/lib/tree/declaration-var.js +63 -0
- package/lib/tree/declaration-var.js.map +1 -0
- package/lib/tree/declaration.d.ts +78 -0
- package/lib/tree/declaration.d.ts.map +1 -0
- package/lib/tree/declaration.js +289 -0
- package/lib/tree/declaration.js.map +1 -0
- package/lib/tree/default-guard.d.ts +15 -0
- package/lib/tree/default-guard.d.ts.map +1 -0
- package/lib/tree/default-guard.js +19 -0
- package/lib/tree/default-guard.js.map +1 -0
- package/lib/tree/dimension.d.ts +33 -0
- package/lib/tree/dimension.d.ts.map +1 -0
- package/lib/tree/dimension.js +291 -0
- package/lib/tree/dimension.js.map +1 -0
- package/lib/tree/expression.d.ts +24 -0
- package/lib/tree/expression.d.ts.map +1 -0
- package/lib/tree/expression.js +28 -0
- package/lib/tree/expression.js.map +1 -0
- package/lib/tree/extend-list.d.ts +23 -0
- package/lib/tree/extend-list.d.ts.map +1 -0
- package/lib/tree/extend-list.js +20 -0
- package/lib/tree/extend-list.js.map +1 -0
- package/lib/tree/extend.d.ts +47 -0
- package/lib/tree/extend.d.ts.map +1 -0
- package/lib/tree/extend.js +292 -0
- package/lib/tree/extend.js.map +1 -0
- package/lib/tree/function.d.ts +48 -0
- package/lib/tree/function.d.ts.map +1 -0
- package/lib/tree/function.js +74 -0
- package/lib/tree/function.js.map +1 -0
- package/lib/tree/import-js.d.ts +35 -0
- package/lib/tree/import-js.d.ts.map +1 -0
- package/lib/tree/import-js.js +45 -0
- package/lib/tree/import-js.js.map +1 -0
- package/lib/tree/import-style.d.ts +156 -0
- package/lib/tree/import-style.d.ts.map +1 -0
- package/lib/tree/import-style.js +556 -0
- package/lib/tree/import-style.js.map +1 -0
- package/lib/tree/index.d.ts +71 -0
- package/lib/tree/index.d.ts.map +1 -0
- package/lib/tree/index.js +95 -0
- package/lib/tree/index.js.map +1 -0
- package/lib/tree/interpolated-reference.d.ts +24 -0
- package/lib/tree/interpolated-reference.d.ts.map +1 -0
- package/lib/tree/interpolated-reference.js +37 -0
- package/lib/tree/interpolated-reference.js.map +1 -0
- package/lib/tree/interpolated.d.ts +62 -0
- package/lib/tree/interpolated.d.ts.map +1 -0
- package/lib/tree/interpolated.js +204 -0
- package/lib/tree/interpolated.js.map +1 -0
- package/lib/tree/js-array.d.ts +10 -0
- package/lib/tree/js-array.d.ts.map +1 -0
- package/lib/tree/js-array.js +10 -0
- package/lib/tree/js-array.js.map +1 -0
- package/lib/tree/js-expr.d.ts +23 -0
- package/lib/tree/js-expr.d.ts.map +1 -0
- package/lib/tree/js-expr.js +28 -0
- package/lib/tree/js-expr.js.map +1 -0
- package/lib/tree/js-function.d.ts +20 -0
- package/lib/tree/js-function.d.ts.map +1 -0
- package/lib/tree/js-function.js +16 -0
- package/lib/tree/js-function.js.map +1 -0
- package/lib/tree/js-object.d.ts +10 -0
- package/lib/tree/js-object.d.ts.map +1 -0
- package/lib/tree/js-object.js +10 -0
- package/lib/tree/js-object.js.map +1 -0
- package/lib/tree/list.d.ts +38 -0
- package/lib/tree/list.d.ts.map +1 -0
- package/lib/tree/list.js +83 -0
- package/lib/tree/list.js.map +1 -0
- package/lib/tree/log.d.ts +29 -0
- package/lib/tree/log.d.ts.map +1 -0
- package/lib/tree/log.js +56 -0
- package/lib/tree/log.js.map +1 -0
- package/lib/tree/mixin.d.ts +87 -0
- package/lib/tree/mixin.d.ts.map +1 -0
- package/lib/tree/mixin.js +112 -0
- package/lib/tree/mixin.js.map +1 -0
- package/lib/tree/negative.d.ts +17 -0
- package/lib/tree/negative.d.ts.map +1 -0
- package/lib/tree/negative.js +22 -0
- package/lib/tree/negative.js.map +1 -0
- package/lib/tree/nil.d.ts +31 -0
- package/lib/tree/nil.d.ts.map +1 -0
- package/lib/tree/nil.js +36 -0
- package/lib/tree/nil.js.map +1 -0
- package/lib/tree/node-base.d.ts +359 -0
- package/lib/tree/node-base.d.ts.map +1 -0
- package/lib/tree/node-base.js +884 -0
- package/lib/tree/node-base.js.map +1 -0
- package/lib/tree/node.d.ts +10 -0
- package/lib/tree/node.d.ts.map +1 -0
- package/lib/tree/node.js +45 -0
- package/lib/tree/node.js.map +1 -0
- package/lib/tree/number.d.ts +21 -0
- package/lib/tree/number.d.ts.map +1 -0
- package/lib/tree/number.js +27 -0
- package/lib/tree/number.js.map +1 -0
- package/lib/tree/operation.d.ts +26 -0
- package/lib/tree/operation.d.ts.map +1 -0
- package/lib/tree/operation.js +103 -0
- package/lib/tree/operation.js.map +1 -0
- package/lib/tree/paren.d.ts +18 -0
- package/lib/tree/paren.d.ts.map +1 -0
- package/lib/tree/paren.js +86 -0
- package/lib/tree/paren.js.map +1 -0
- package/lib/tree/query-condition.d.ts +17 -0
- package/lib/tree/query-condition.d.ts.map +1 -0
- package/lib/tree/query-condition.js +39 -0
- package/lib/tree/query-condition.js.map +1 -0
- package/lib/tree/quoted.d.ts +27 -0
- package/lib/tree/quoted.d.ts.map +1 -0
- package/lib/tree/quoted.js +66 -0
- package/lib/tree/quoted.js.map +1 -0
- package/lib/tree/range.d.ts +33 -0
- package/lib/tree/range.d.ts.map +1 -0
- package/lib/tree/range.js +47 -0
- package/lib/tree/range.js.map +1 -0
- package/lib/tree/reference.d.ts +76 -0
- package/lib/tree/reference.d.ts.map +1 -0
- package/lib/tree/reference.js +521 -0
- package/lib/tree/reference.js.map +1 -0
- package/lib/tree/rest.d.ts +15 -0
- package/lib/tree/rest.d.ts.map +1 -0
- package/lib/tree/rest.js +32 -0
- package/lib/tree/rest.js.map +1 -0
- package/lib/tree/rules-raw.d.ts +17 -0
- package/lib/tree/rules-raw.d.ts.map +1 -0
- package/lib/tree/rules-raw.js +37 -0
- package/lib/tree/rules-raw.js.map +1 -0
- package/lib/tree/rules.d.ts +255 -0
- package/lib/tree/rules.d.ts.map +1 -0
- package/lib/tree/rules.js +2293 -0
- package/lib/tree/rules.js.map +1 -0
- package/lib/tree/ruleset.d.ts +91 -0
- package/lib/tree/ruleset.d.ts.map +1 -0
- package/lib/tree/ruleset.js +506 -0
- package/lib/tree/ruleset.js.map +1 -0
- package/lib/tree/selector-attr.d.ts +31 -0
- package/lib/tree/selector-attr.d.ts.map +1 -0
- package/lib/tree/selector-attr.js +99 -0
- package/lib/tree/selector-attr.js.map +1 -0
- package/lib/tree/selector-basic.d.ts +23 -0
- package/lib/tree/selector-basic.d.ts.map +1 -0
- package/lib/tree/selector-basic.js +34 -0
- package/lib/tree/selector-basic.js.map +1 -0
- package/lib/tree/selector-capture.d.ts +23 -0
- package/lib/tree/selector-capture.d.ts.map +1 -0
- package/lib/tree/selector-capture.js +34 -0
- package/lib/tree/selector-capture.js.map +1 -0
- package/lib/tree/selector-complex.d.ts +40 -0
- package/lib/tree/selector-complex.d.ts.map +1 -0
- package/lib/tree/selector-complex.js +143 -0
- package/lib/tree/selector-complex.js.map +1 -0
- package/lib/tree/selector-compound.d.ts +16 -0
- package/lib/tree/selector-compound.d.ts.map +1 -0
- package/lib/tree/selector-compound.js +114 -0
- package/lib/tree/selector-compound.js.map +1 -0
- package/lib/tree/selector-interpolated.d.ts +23 -0
- package/lib/tree/selector-interpolated.d.ts.map +1 -0
- package/lib/tree/selector-interpolated.js +27 -0
- package/lib/tree/selector-interpolated.js.map +1 -0
- package/lib/tree/selector-list.d.ts +17 -0
- package/lib/tree/selector-list.d.ts.map +1 -0
- package/lib/tree/selector-list.js +184 -0
- package/lib/tree/selector-list.js.map +1 -0
- package/lib/tree/selector-pseudo.d.ts +42 -0
- package/lib/tree/selector-pseudo.d.ts.map +1 -0
- package/lib/tree/selector-pseudo.js +191 -0
- package/lib/tree/selector-pseudo.js.map +1 -0
- package/lib/tree/selector-simple.d.ts +5 -0
- package/lib/tree/selector-simple.d.ts.map +1 -0
- package/lib/tree/selector-simple.js +6 -0
- package/lib/tree/selector-simple.js.map +1 -0
- package/lib/tree/selector.d.ts +43 -0
- package/lib/tree/selector.d.ts.map +1 -0
- package/lib/tree/selector.js +56 -0
- package/lib/tree/selector.js.map +1 -0
- package/lib/tree/sequence.d.ts +43 -0
- package/lib/tree/sequence.d.ts.map +1 -0
- package/lib/tree/sequence.js +148 -0
- package/lib/tree/sequence.js.map +1 -0
- package/lib/tree/tree.d.ts +87 -0
- package/lib/tree/tree.d.ts.map +1 -0
- package/lib/tree/tree.js +2 -0
- package/lib/tree/tree.js.map +1 -0
- package/lib/tree/url.d.ts +18 -0
- package/lib/tree/url.d.ts.map +1 -0
- package/lib/tree/url.js +35 -0
- package/lib/tree/url.js.map +1 -0
- package/lib/tree/util/__tests__/debug-log.d.ts +1 -0
- package/lib/tree/util/__tests__/debug-log.d.ts.map +1 -0
- package/lib/tree/util/__tests__/debug-log.js +36 -0
- package/lib/tree/util/__tests__/debug-log.js.map +1 -0
- package/lib/tree/util/calculate.d.ts +3 -0
- package/lib/tree/util/calculate.d.ts.map +1 -0
- package/lib/tree/util/calculate.js +10 -0
- package/lib/tree/util/calculate.js.map +1 -0
- package/lib/tree/util/cast.d.ts +10 -0
- package/lib/tree/util/cast.d.ts.map +1 -0
- package/lib/tree/util/cast.js +87 -0
- package/lib/tree/util/cast.js.map +1 -0
- package/lib/tree/util/cloning.d.ts +4 -0
- package/lib/tree/util/cloning.d.ts.map +1 -0
- package/lib/tree/util/cloning.js +8 -0
- package/lib/tree/util/cloning.js.map +1 -0
- package/lib/tree/util/collections.d.ts +57 -0
- package/lib/tree/util/collections.d.ts.map +1 -0
- package/lib/tree/util/collections.js +136 -0
- package/lib/tree/util/collections.js.map +1 -0
- package/lib/tree/util/compare.d.ts +11 -0
- package/lib/tree/util/compare.d.ts.map +1 -0
- package/lib/tree/util/compare.js +89 -0
- package/lib/tree/util/compare.js.map +1 -0
- package/lib/tree/util/extend-helpers.d.ts +2 -0
- package/lib/tree/util/extend-helpers.d.ts.map +1 -0
- package/lib/tree/util/extend-helpers.js +2 -0
- package/lib/tree/util/extend-helpers.js.map +1 -0
- package/lib/tree/util/extend-roots.d.ts +37 -0
- package/lib/tree/util/extend-roots.d.ts.map +1 -0
- package/lib/tree/util/extend-roots.js +682 -0
- package/lib/tree/util/extend-roots.js.map +1 -0
- package/lib/tree/util/extend-roots.old.d.ts +132 -0
- package/lib/tree/util/extend-roots.old.d.ts.map +1 -0
- package/lib/tree/util/extend-roots.old.js +2272 -0
- package/lib/tree/util/extend-roots.old.js.map +1 -0
- package/lib/tree/util/extend-trace-debug.d.ts +13 -0
- package/lib/tree/util/extend-trace-debug.d.ts.map +1 -0
- package/lib/tree/util/extend-trace-debug.js +34 -0
- package/lib/tree/util/extend-trace-debug.js.map +1 -0
- package/lib/tree/util/extend.d.ts +218 -0
- package/lib/tree/util/extend.d.ts.map +1 -0
- package/lib/tree/util/extend.js +3033 -0
- package/lib/tree/util/extend.js.map +1 -0
- package/lib/tree/util/find-extendable-locations.d.ts +2 -0
- package/lib/tree/util/find-extendable-locations.d.ts.map +1 -0
- package/lib/tree/util/find-extendable-locations.js +2 -0
- package/lib/tree/util/find-extendable-locations.js.map +1 -0
- package/lib/tree/util/format.d.ts +20 -0
- package/lib/tree/util/format.d.ts.map +1 -0
- package/lib/tree/util/format.js +67 -0
- package/lib/tree/util/format.js.map +1 -0
- package/lib/tree/util/is-node.d.ts +13 -0
- package/lib/tree/util/is-node.d.ts.map +1 -0
- package/lib/tree/util/is-node.js +43 -0
- package/lib/tree/util/is-node.js.map +1 -0
- package/lib/tree/util/print.d.ts +80 -0
- package/lib/tree/util/print.d.ts.map +1 -0
- package/lib/tree/util/print.js +205 -0
- package/lib/tree/util/print.js.map +1 -0
- package/lib/tree/util/process-leading-is.d.ts +25 -0
- package/lib/tree/util/process-leading-is.d.ts.map +1 -0
- package/lib/tree/util/process-leading-is.js +364 -0
- package/lib/tree/util/process-leading-is.js.map +1 -0
- package/lib/tree/util/recursion-helper.d.ts +15 -0
- package/lib/tree/util/recursion-helper.d.ts.map +1 -0
- package/lib/tree/util/recursion-helper.js +43 -0
- package/lib/tree/util/recursion-helper.js.map +1 -0
- package/lib/tree/util/regex.d.ts +4 -0
- package/lib/tree/util/regex.d.ts.map +1 -0
- package/lib/tree/util/regex.js +4 -0
- package/lib/tree/util/regex.js.map +1 -0
- package/lib/tree/util/registry-utils.d.ts +192 -0
- package/lib/tree/util/registry-utils.d.ts.map +1 -0
- package/lib/tree/util/registry-utils.js +1242 -0
- package/lib/tree/util/registry-utils.js.map +1 -0
- package/lib/tree/util/ruleset-trace.d.ts +4 -0
- package/lib/tree/util/ruleset-trace.d.ts.map +1 -0
- package/lib/tree/util/ruleset-trace.js +14 -0
- package/lib/tree/util/ruleset-trace.js.map +1 -0
- package/lib/tree/util/selector-compare.d.ts +2 -0
- package/lib/tree/util/selector-compare.d.ts.map +1 -0
- package/lib/tree/util/selector-compare.js +2 -0
- package/lib/tree/util/selector-compare.js.map +1 -0
- package/lib/tree/util/selector-match-core.d.ts +171 -0
- package/lib/tree/util/selector-match-core.d.ts.map +1 -0
- package/lib/tree/util/selector-match-core.js +1578 -0
- package/lib/tree/util/selector-match-core.js.map +1 -0
- package/lib/tree/util/selector-utils.d.ts +30 -0
- package/lib/tree/util/selector-utils.d.ts.map +1 -0
- package/lib/tree/util/selector-utils.js +100 -0
- package/lib/tree/util/selector-utils.js.map +1 -0
- package/lib/tree/util/serialize-helper.d.ts +13 -0
- package/lib/tree/util/serialize-helper.d.ts.map +1 -0
- package/lib/tree/util/serialize-helper.js +387 -0
- package/lib/tree/util/serialize-helper.js.map +1 -0
- package/lib/tree/util/serialize-types.d.ts +9 -0
- package/lib/tree/util/serialize-types.d.ts.map +1 -0
- package/lib/tree/util/serialize-types.js +216 -0
- package/lib/tree/util/serialize-types.js.map +1 -0
- package/lib/tree/util/should-operate.d.ts +23 -0
- package/lib/tree/util/should-operate.d.ts.map +1 -0
- package/lib/tree/util/should-operate.js +46 -0
- package/lib/tree/util/should-operate.js.map +1 -0
- package/lib/tree/util/sourcemap.d.ts +7 -0
- package/lib/tree/util/sourcemap.d.ts.map +1 -0
- package/lib/tree/util/sourcemap.js +25 -0
- package/lib/tree/util/sourcemap.js.map +1 -0
- package/lib/types/config.d.ts +205 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/config.js +2 -0
- package/lib/types/config.js.map +1 -0
- package/lib/types/index.d.ts +15 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +3 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/modes.d.ts +24 -0
- package/lib/types/modes.d.ts.map +1 -0
- package/lib/types/modes.js +2 -0
- package/lib/types/modes.js.map +1 -0
- package/lib/types.d.ts +61 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/lib/use-webpack-resolver.d.ts +9 -0
- package/lib/use-webpack-resolver.d.ts.map +1 -0
- package/lib/use-webpack-resolver.js +41 -0
- package/lib/use-webpack-resolver.js.map +1 -0
- package/lib/visitor/index.d.ts +136 -0
- package/lib/visitor/index.d.ts.map +1 -0
- package/lib/visitor/index.js +135 -0
- package/lib/visitor/index.js.map +1 -0
- package/lib/visitor/less-visitor.d.ts +7 -0
- package/lib/visitor/less-visitor.d.ts.map +1 -0
- package/lib/visitor/less-visitor.js +7 -0
- package/lib/visitor/less-visitor.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,884 @@
|
|
|
1
|
+
import isPlainObject from 'lodash-es/isPlainObject.js';
|
|
2
|
+
import { getEntriesFromNode, getValues } from './util/collections.js';
|
|
3
|
+
import { getPrintOptions } from './util/print.js';
|
|
4
|
+
import { pipe, isThenable, serialForEach } from '@jesscss/awaitable-pipe';
|
|
5
|
+
const { isArray } = Array;
|
|
6
|
+
const primitives = ['undefined', 'boolean', 'string', 'number'];
|
|
7
|
+
export const ABORT = Symbol('ABORT');
|
|
8
|
+
export const REMOVE = Symbol('REMOVE');
|
|
9
|
+
export const IS_PROXY = Symbol('IS_PROXY');
|
|
10
|
+
export const DEFAULT_DATA = 'value';
|
|
11
|
+
/**
|
|
12
|
+
* @todo I think the only utility for this now is we collect
|
|
13
|
+
* the types of nodes in the tree at first evaluation time.
|
|
14
|
+
*/
|
|
15
|
+
export const defineType = (Clazz, type, shortType) => {
|
|
16
|
+
shortType ??= type.toLowerCase();
|
|
17
|
+
Clazz.type = type;
|
|
18
|
+
Clazz.shortType = shortType;
|
|
19
|
+
let proto = Clazz;
|
|
20
|
+
let types = proto.types = new Set();
|
|
21
|
+
while (proto?.type) {
|
|
22
|
+
types.add(proto.type);
|
|
23
|
+
proto = Object.getPrototypeOf(proto);
|
|
24
|
+
}
|
|
25
|
+
return (...args) => {
|
|
26
|
+
const node = new Clazz(...args);
|
|
27
|
+
node.type = type;
|
|
28
|
+
node.shortType = shortType;
|
|
29
|
+
return node;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
// Node state flags as bitmask
|
|
33
|
+
export const F_VISIBLE = 0b1;
|
|
34
|
+
export const F_MAY_ASYNC = 0b10;
|
|
35
|
+
/**
|
|
36
|
+
* @todo - The plan is to use these as signals for evaluation. If we
|
|
37
|
+
* bubble these correctly, then we can exit early from evaluation for
|
|
38
|
+
* a speed boost. However, bubbling is not yet water-tight and needs
|
|
39
|
+
* test coverage.
|
|
40
|
+
*/
|
|
41
|
+
export const F_STATIC = 0b100;
|
|
42
|
+
export const F_NON_STATIC = 0b1000;
|
|
43
|
+
/** Whether or not a physical ampersand is in this selector */
|
|
44
|
+
export const F_AMPERSAND = 0b10000;
|
|
45
|
+
/** Whether an ampersand was implicitly added (not written by user) */
|
|
46
|
+
export const F_IMPLICIT_AMPERSAND = 0b100000;
|
|
47
|
+
/** Selector item produced by extend and eligible for reference-mode rendering. */
|
|
48
|
+
export const F_EXTENDED = 0b1000000;
|
|
49
|
+
/** Selector item that matches an extend target and should be suppressed in reference-mode output. */
|
|
50
|
+
export const F_EXTEND_TARGET = 0b10000000;
|
|
51
|
+
// Default state: only visible is true
|
|
52
|
+
export const F_DEFAULT = F_VISIBLE;
|
|
53
|
+
// Future flags can be added here
|
|
54
|
+
// export const CACHED = 0b1000000;
|
|
55
|
+
// export const DIRTY = 0b10000000;
|
|
56
|
+
// export const LOCKED = 0b100000000;
|
|
57
|
+
// const FULLY_EVALUATED = F_EVALUATED | F_PRE_EVALUATED;
|
|
58
|
+
/**
|
|
59
|
+
* The underlying type for all Jess nodes
|
|
60
|
+
*/
|
|
61
|
+
export class Node {
|
|
62
|
+
_location;
|
|
63
|
+
get location() {
|
|
64
|
+
return (this._location ??= []);
|
|
65
|
+
}
|
|
66
|
+
_treeContext;
|
|
67
|
+
_options;
|
|
68
|
+
get options() {
|
|
69
|
+
return (this._options ??= {});
|
|
70
|
+
}
|
|
71
|
+
set options(options) {
|
|
72
|
+
this._options = options;
|
|
73
|
+
}
|
|
74
|
+
get types() {
|
|
75
|
+
return this.constructor.types;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Whitespace or comments before or after a Node.
|
|
79
|
+
*
|
|
80
|
+
* If this is `1`, it represents a single space character (' ').
|
|
81
|
+
* If it's 0, it means there were no pre/post tokens when parsed.
|
|
82
|
+
* If undefined, it means this was created using the API, and default
|
|
83
|
+
* formatting can be used.
|
|
84
|
+
* In a NodeList, any whitespace tokens outside of comments are individually represented,
|
|
85
|
+
* because they are preserved while the comment may not be.
|
|
86
|
+
*/
|
|
87
|
+
/** Nil type is resolved at runtime via prototype patching */
|
|
88
|
+
pre;
|
|
89
|
+
post;
|
|
90
|
+
/** Will be copied during inherit */
|
|
91
|
+
state = F_DEFAULT;
|
|
92
|
+
/** Runtime tracking: has preEval been run on this node? */
|
|
93
|
+
preEvaluated = false;
|
|
94
|
+
/** Runtime tracking: has eval been run on this node? */
|
|
95
|
+
evaluated = false;
|
|
96
|
+
get visible() {
|
|
97
|
+
return this.hasFlag(F_VISIBLE);
|
|
98
|
+
}
|
|
99
|
+
allowRoot = false;
|
|
100
|
+
allowRuleRoot = false;
|
|
101
|
+
hoistToRoot = undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Code internally should call .create() when making new
|
|
104
|
+
* nodes, which will automatically mark the node as generated.
|
|
105
|
+
*/
|
|
106
|
+
generated = false;
|
|
107
|
+
/**
|
|
108
|
+
* If the node must have a semi separator before
|
|
109
|
+
* the next node when in a declaration list or main
|
|
110
|
+
* rules list.
|
|
111
|
+
*/
|
|
112
|
+
_requiredSemi = false;
|
|
113
|
+
get requiredSemi() {
|
|
114
|
+
return this._requiredSemi;
|
|
115
|
+
}
|
|
116
|
+
set requiredSemi(value) {
|
|
117
|
+
this._requiredSemi = value;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* When evaluating, nodes are assigned an index and depth by the Rules node.
|
|
121
|
+
* This is used for lookup order. Note, this _will_ be undefined
|
|
122
|
+
* initially, but we assign it in the Rules node, which is also
|
|
123
|
+
* where we read it, so this makes the type easier.
|
|
124
|
+
*/
|
|
125
|
+
index;
|
|
126
|
+
/** @todo - Is there a reliable way to cache this? */
|
|
127
|
+
get depth() {
|
|
128
|
+
let node = this.rulesParent;
|
|
129
|
+
let depth = 0;
|
|
130
|
+
while (node) {
|
|
131
|
+
depth++;
|
|
132
|
+
node = node.rulesParent;
|
|
133
|
+
}
|
|
134
|
+
return depth;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* If true, prevents re-parenting of this node.
|
|
138
|
+
* This is used to maintain source lookup chains.
|
|
139
|
+
*/
|
|
140
|
+
frozen = false;
|
|
141
|
+
_value;
|
|
142
|
+
/**
|
|
143
|
+
* This is the internal `data` of the node.
|
|
144
|
+
*/
|
|
145
|
+
get value() {
|
|
146
|
+
return this._value;
|
|
147
|
+
}
|
|
148
|
+
set value(val) {
|
|
149
|
+
this._value = this._tryProxyWrap(val);
|
|
150
|
+
// Invalidate memoized valueOf() on selector-like nodes after mutation.
|
|
151
|
+
if ('_valueOf' in this) {
|
|
152
|
+
this._valueOf = undefined;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* This wraps the value in a proxy if it's an object or array.
|
|
157
|
+
* We do this so that assignment to the sub-nodes will properly
|
|
158
|
+
* set the parent of the sub-nodes.
|
|
159
|
+
*
|
|
160
|
+
* @todo - Test parent setting for objects / arrays.
|
|
161
|
+
*/
|
|
162
|
+
_tryProxyWrap(value) {
|
|
163
|
+
if (isPlainObject(value) || isArray(value)) {
|
|
164
|
+
value = this._processNodes(value);
|
|
165
|
+
return new Proxy(value, {
|
|
166
|
+
get: (target, prop) => {
|
|
167
|
+
if (prop === IS_PROXY) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
const returnVal = Reflect.get(target, prop);
|
|
171
|
+
if (isPlainObject(returnVal) || isArray(returnVal)) {
|
|
172
|
+
if (returnVal[IS_PROXY]) {
|
|
173
|
+
/** Already a proxy so don't re-wrap it */
|
|
174
|
+
return returnVal;
|
|
175
|
+
}
|
|
176
|
+
return this._tryProxyWrap(returnVal);
|
|
177
|
+
}
|
|
178
|
+
return returnVal;
|
|
179
|
+
},
|
|
180
|
+
set: (target, prop, newValue) => {
|
|
181
|
+
if (isPlainObject(newValue) || isArray(newValue)) {
|
|
182
|
+
newValue = this._processNodes(newValue);
|
|
183
|
+
}
|
|
184
|
+
if (newValue instanceof Node) {
|
|
185
|
+
this.adopt(newValue);
|
|
186
|
+
}
|
|
187
|
+
return Reflect.set(target, prop, newValue);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return this._processNodes(value);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Add a flag to the node's state
|
|
195
|
+
* Handles STATIC/NON_STATIC exclusivity automatically
|
|
196
|
+
*/
|
|
197
|
+
addFlag(flag) {
|
|
198
|
+
// NON_STATIC takes precedence over STATIC
|
|
199
|
+
if (flag === F_STATIC && this.hasFlag(F_NON_STATIC)) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
this.state |= flag;
|
|
203
|
+
// Handle STATIC/NON_STATIC exclusivity
|
|
204
|
+
if (flag === F_NON_STATIC) {
|
|
205
|
+
this.state &= ~F_STATIC;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Remove a flag from the node's state
|
|
210
|
+
*/
|
|
211
|
+
removeFlag(flag) {
|
|
212
|
+
this.state &= ~flag;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Check if the node has a specific flag
|
|
216
|
+
*/
|
|
217
|
+
hasFlag(flag) {
|
|
218
|
+
return (this.state & flag) !== 0;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Add multiple flags to the node's state
|
|
222
|
+
*/
|
|
223
|
+
addFlags(...flags) {
|
|
224
|
+
for (const flag of flags) {
|
|
225
|
+
this.addFlag(flag);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
adopt(node) {
|
|
229
|
+
/** The only place we should do this */
|
|
230
|
+
if (!node.frozen) {
|
|
231
|
+
node.parent = this;
|
|
232
|
+
}
|
|
233
|
+
if (node.hasFlag(F_NON_STATIC)) {
|
|
234
|
+
this.addFlag(F_NON_STATIC);
|
|
235
|
+
this.removeFlag(F_STATIC);
|
|
236
|
+
}
|
|
237
|
+
else if (node.hasFlag(F_STATIC)) {
|
|
238
|
+
this.addFlag(F_STATIC);
|
|
239
|
+
}
|
|
240
|
+
if (node.hasFlag(F_MAY_ASYNC)) {
|
|
241
|
+
this.addFlag(F_MAY_ASYNC);
|
|
242
|
+
}
|
|
243
|
+
if (node.hasFlag(F_AMPERSAND) && this.type !== 'Rules') {
|
|
244
|
+
this.addFlag(F_AMPERSAND);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Assign parent to sub-nodes
|
|
249
|
+
* @note - This will not process the children nodes of children nodes.
|
|
250
|
+
*/
|
|
251
|
+
_processNodes(value) {
|
|
252
|
+
for (let val of getValues(value)) {
|
|
253
|
+
if (val instanceof Node) {
|
|
254
|
+
this.adopt(val);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return value;
|
|
258
|
+
}
|
|
259
|
+
constructor(value, options, location, treeContext) {
|
|
260
|
+
// Make some props non-enumerable to avoid JSON serialization issues
|
|
261
|
+
Object.defineProperties(this, {
|
|
262
|
+
sourceNode: {
|
|
263
|
+
value: this,
|
|
264
|
+
writable: true,
|
|
265
|
+
enumerable: false,
|
|
266
|
+
configurable: false
|
|
267
|
+
},
|
|
268
|
+
parent: {
|
|
269
|
+
value: undefined,
|
|
270
|
+
writable: true,
|
|
271
|
+
enumerable: false,
|
|
272
|
+
configurable: false
|
|
273
|
+
},
|
|
274
|
+
sourceParent: {
|
|
275
|
+
value: undefined,
|
|
276
|
+
writable: true,
|
|
277
|
+
enumerable: false,
|
|
278
|
+
configurable: false
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
this._value = this._tryProxyWrap(value);
|
|
282
|
+
this._treeContext = treeContext;
|
|
283
|
+
this._location = location;
|
|
284
|
+
this._options = options;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Static factory method to create a generated node.
|
|
288
|
+
* Has the exact same signature as the constructor but automatically marks the node as generated.
|
|
289
|
+
*
|
|
290
|
+
* @param value - The node's value data
|
|
291
|
+
* @param options - Node options
|
|
292
|
+
* @param location - Location information
|
|
293
|
+
* @param treeContext - Tree context
|
|
294
|
+
* @returns A new node instance with generated flag set if applicable
|
|
295
|
+
*/
|
|
296
|
+
static create(value, options, location, treeContext) {
|
|
297
|
+
// Create the instance with the same signature as constructor
|
|
298
|
+
const instance = new this(value, options, location, treeContext);
|
|
299
|
+
// Mark as generated if the value is an object that can be marked
|
|
300
|
+
if (instance instanceof Node) {
|
|
301
|
+
instance.generated = true;
|
|
302
|
+
}
|
|
303
|
+
return instance;
|
|
304
|
+
}
|
|
305
|
+
get rulesParent() {
|
|
306
|
+
let possibleRules = this.parent;
|
|
307
|
+
while (possibleRules && possibleRules.type !== 'Rules') {
|
|
308
|
+
possibleRules = possibleRules.parent;
|
|
309
|
+
}
|
|
310
|
+
return possibleRules;
|
|
311
|
+
}
|
|
312
|
+
get sourceRulesParent() {
|
|
313
|
+
let node = this.parent;
|
|
314
|
+
let sourceParent = this.sourceParent;
|
|
315
|
+
while (node && !sourceParent) {
|
|
316
|
+
node = node.parent;
|
|
317
|
+
sourceParent = node?.sourceParent;
|
|
318
|
+
}
|
|
319
|
+
return sourceParent?.rulesParent;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Mutates node children in place. Used by eval()?
|
|
323
|
+
*
|
|
324
|
+
* Processed nodes must always return a Node.
|
|
325
|
+
*/
|
|
326
|
+
forEachNode(func) {
|
|
327
|
+
const entries = [...getEntriesFromNode(this)];
|
|
328
|
+
return serialForEach(entries, ([value, key, collection], idx) => {
|
|
329
|
+
if (!(value instanceof Node)) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const out = func(value, idx);
|
|
333
|
+
if (isThenable(out)) {
|
|
334
|
+
return out.then((result) => {
|
|
335
|
+
collection[key] = result;
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
collection[key] = out;
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
static *nodeAndPrePost(node) {
|
|
342
|
+
if (isArray(node.pre)) {
|
|
343
|
+
for (let n of node.pre) {
|
|
344
|
+
if (n instanceof Node) {
|
|
345
|
+
yield n;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
yield node;
|
|
350
|
+
if (isArray(node.post)) {
|
|
351
|
+
for (let n of node.post) {
|
|
352
|
+
if (n instanceof Node) {
|
|
353
|
+
yield n;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Return an iterator for all nodes / children nodes, including this one
|
|
360
|
+
*/
|
|
361
|
+
*nodes(reverse, includePrePost) {
|
|
362
|
+
if (includePrePost) {
|
|
363
|
+
yield* Node.nodeAndPrePost(this);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
yield this;
|
|
367
|
+
}
|
|
368
|
+
yield* this.children(true, reverse, includePrePost);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* An iterator for all node children
|
|
372
|
+
* @todo - Replace `walkNodes` with this?
|
|
373
|
+
*/
|
|
374
|
+
*children(deep, reverse, includePrePost) {
|
|
375
|
+
for (let nodeVal of getValues(this.value, reverse)) {
|
|
376
|
+
if (nodeVal instanceof Node) {
|
|
377
|
+
if (includePrePost) {
|
|
378
|
+
yield* Node.nodeAndPrePost(nodeVal);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
yield nodeVal;
|
|
382
|
+
}
|
|
383
|
+
if (deep) {
|
|
384
|
+
yield* nodeVal.children(deep, reverse, includePrePost);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* @todo - Remove?
|
|
391
|
+
*/
|
|
392
|
+
// collectRoots(): Node[] {
|
|
393
|
+
// let list: Node[] = []
|
|
394
|
+
// this.walkNodes(n => {
|
|
395
|
+
// if (n.type === 'Rules') {
|
|
396
|
+
// const rules = n.rootRules
|
|
397
|
+
// if (rules) {
|
|
398
|
+
// for (let n of rules) {
|
|
399
|
+
// list.push(n)
|
|
400
|
+
// }
|
|
401
|
+
// n.rootRules = undefined
|
|
402
|
+
// }
|
|
403
|
+
// }
|
|
404
|
+
// })
|
|
405
|
+
// return list
|
|
406
|
+
// }
|
|
407
|
+
/**
|
|
408
|
+
* Accept a visitor (classic visitor pattern).
|
|
409
|
+
*
|
|
410
|
+
* Visits the node itself first, then recursively visits children.
|
|
411
|
+
* This matches the Less.js visitor pattern and allows nodes to control
|
|
412
|
+
* their own traversal if needed by overriding this method.
|
|
413
|
+
*
|
|
414
|
+
* @param visitor - The visitor to accept
|
|
415
|
+
* @returns The result from visiting this node (may be a replacement node)
|
|
416
|
+
*/
|
|
417
|
+
accept(visitor) {
|
|
418
|
+
// Visit self first (like Less.js pattern).
|
|
419
|
+
// Support both Visitor class instances (visit()) and plain visitor objects.
|
|
420
|
+
let result = this;
|
|
421
|
+
const treeVisitMethod = visitor._visit;
|
|
422
|
+
const hasTreeVisitorState = visitor.visitedNodes instanceof Set;
|
|
423
|
+
const visitMethod = visitor.visit;
|
|
424
|
+
if (typeof treeVisitMethod === 'function' && hasTreeVisitorState) {
|
|
425
|
+
result = treeVisitMethod.call(visitor, this, {});
|
|
426
|
+
}
|
|
427
|
+
else if (typeof visitMethod === 'function') {
|
|
428
|
+
result = visitMethod.call(visitor, this);
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
const maybeAbort = visitor.enter?.(this);
|
|
432
|
+
if (maybeAbort === ABORT) {
|
|
433
|
+
return this;
|
|
434
|
+
}
|
|
435
|
+
const methodName = this.type.charAt(0).toLowerCase() + this.type.slice(1);
|
|
436
|
+
const typeMethod = visitor[methodName];
|
|
437
|
+
if (typeof typeMethod === 'function') {
|
|
438
|
+
const visited = typeMethod.call(visitor, this);
|
|
439
|
+
if (visited) {
|
|
440
|
+
result = visited;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
result = visitor.exit?.(result) ?? result;
|
|
444
|
+
}
|
|
445
|
+
// Visit children recursively (Less.js pattern)
|
|
446
|
+
// Note: If TreeVisitor is using accept(), it will skip auto-visiting children
|
|
447
|
+
// to avoid double-visiting. See TreeVisitor._visit() implementation.
|
|
448
|
+
for (const child of this.children()) {
|
|
449
|
+
if (child.accept) {
|
|
450
|
+
child.accept(visitor);
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
// Fallback: if child doesn't have accept, visit directly
|
|
454
|
+
visitor.visit(child);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
// Return the result (may be a replacement node)
|
|
458
|
+
return result instanceof Node ? result : this;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* @todo
|
|
462
|
+
* Write tests that make sure that a maybe clone without preserveOriginalNodes
|
|
463
|
+
* does not clone the nodes, but a maybeClone with preserveOriginalNodes
|
|
464
|
+
* does clone the nodes all through the tree.
|
|
465
|
+
*/
|
|
466
|
+
maybeClone(context, deep, cloneFn) {
|
|
467
|
+
if (context.preserveOriginalNodes) {
|
|
468
|
+
return this.clone(deep, cloneFn);
|
|
469
|
+
}
|
|
470
|
+
return this;
|
|
471
|
+
}
|
|
472
|
+
clonedEval(context) {
|
|
473
|
+
let preserveNodes = context.preserveOriginalNodes;
|
|
474
|
+
context.preserveOriginalNodes = true;
|
|
475
|
+
let out = this.eval(context);
|
|
476
|
+
if (isThenable(out)) {
|
|
477
|
+
return out.then((result) => {
|
|
478
|
+
context.preserveOriginalNodes = preserveNodes;
|
|
479
|
+
return result;
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
context.preserveOriginalNodes = preserveNodes;
|
|
483
|
+
return out;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Creates a copy of the current node.
|
|
487
|
+
*
|
|
488
|
+
* @note - In the Less source, nodes were always cloned before
|
|
489
|
+
* mutating, which is why I did it here. However... the only
|
|
490
|
+
* utility for cloning is to preserve the original node,
|
|
491
|
+
* or (maybe?) to create a copy which is output differently.
|
|
492
|
+
*
|
|
493
|
+
* But... considering the high cost of cloning in terms of
|
|
494
|
+
* object creation, and the low utility of preserving the original
|
|
495
|
+
* node, I think we should just only clone when we need to.
|
|
496
|
+
*/
|
|
497
|
+
clone(deep, cloneFn) {
|
|
498
|
+
let Class = this.constructor;
|
|
499
|
+
let originalValue = this.value;
|
|
500
|
+
let newValue = { value: originalValue };
|
|
501
|
+
/**
|
|
502
|
+
* Create new array objects and plain objects
|
|
503
|
+
*/
|
|
504
|
+
if (isArray(originalValue)) {
|
|
505
|
+
newValue.value = [...originalValue];
|
|
506
|
+
}
|
|
507
|
+
else if (isPlainObject(originalValue)) {
|
|
508
|
+
let map = new Map(Object.entries(originalValue));
|
|
509
|
+
for (let [key, value] of map.entries()) {
|
|
510
|
+
if (isArray(value)) {
|
|
511
|
+
map.set(key, [...value]);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
newValue.value = Object.fromEntries(map);
|
|
515
|
+
}
|
|
516
|
+
cloneFn ??= n => n.clone(deep);
|
|
517
|
+
if (deep) {
|
|
518
|
+
/** I think GetEntriesOf is not typed correctly, thus neither is getEntriesFromNode */
|
|
519
|
+
for (let [value, key, collection] of getEntriesFromNode(newValue)) {
|
|
520
|
+
if (value instanceof Node) {
|
|
521
|
+
collection[key] = cloneFn(value);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
let newNode = new Class(newValue.value, this._options ? { ...this._options } : undefined, this.location, this.treeContext);
|
|
526
|
+
newNode.inherit(this);
|
|
527
|
+
return newNode;
|
|
528
|
+
}
|
|
529
|
+
/** Remove comments from pre/post */
|
|
530
|
+
stripPrePost(n, preOrPost) {
|
|
531
|
+
const prePost = n[preOrPost];
|
|
532
|
+
if (isArray(prePost)) {
|
|
533
|
+
n[preOrPost] = [...prePost];
|
|
534
|
+
for (let [key, node] of prePost.entries()) {
|
|
535
|
+
if (node instanceof Node && node.type === 'Comment') {
|
|
536
|
+
/** Replace comment with a nil node that inherits location */
|
|
537
|
+
const nilNode = this.nil?.() || this._createMinimalNil();
|
|
538
|
+
prePost[key] = nilNode.inherit(node);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
/** Minimal nil fallback for edge cases where prototype method isn't attached yet */
|
|
544
|
+
_createMinimalNil() {
|
|
545
|
+
// @ts-expect-error - normally an abstract class
|
|
546
|
+
const nilish = new Node();
|
|
547
|
+
nilish.type = 'Nil';
|
|
548
|
+
nilish.shortType = 'nil';
|
|
549
|
+
// Override the types getter on this instance to return a Set
|
|
550
|
+
// The types getter normally reads from this.constructor.types
|
|
551
|
+
// We use a get descriptor to override the prototype getter
|
|
552
|
+
const typesSet = new Set(['Nil', 'Node']);
|
|
553
|
+
Object.defineProperty(nilish, 'types', {
|
|
554
|
+
get() {
|
|
555
|
+
return typesSet;
|
|
556
|
+
},
|
|
557
|
+
enumerable: false,
|
|
558
|
+
configurable: false
|
|
559
|
+
});
|
|
560
|
+
nilish.removeFlag(F_VISIBLE);
|
|
561
|
+
nilish.value = '';
|
|
562
|
+
return nilish;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Same as clone except comments are stripped.
|
|
566
|
+
* This is used for variable referencing and
|
|
567
|
+
* selector extending.
|
|
568
|
+
*/
|
|
569
|
+
copy(deep, cloneFn) {
|
|
570
|
+
const newNode = this.clone(deep, (n) => {
|
|
571
|
+
if (n.type !== 'Comment') {
|
|
572
|
+
const copy = n.copy(deep, cloneFn);
|
|
573
|
+
return copy;
|
|
574
|
+
}
|
|
575
|
+
const nilNode = this.nil?.() || this._createMinimalNil();
|
|
576
|
+
return nilNode.inherit(n);
|
|
577
|
+
});
|
|
578
|
+
if (this.hasFlag(F_AMPERSAND)) {
|
|
579
|
+
newNode.addFlag(F_AMPERSAND);
|
|
580
|
+
}
|
|
581
|
+
if (this.hasFlag(F_IMPLICIT_AMPERSAND)) {
|
|
582
|
+
newNode.addFlag(F_IMPLICIT_AMPERSAND);
|
|
583
|
+
}
|
|
584
|
+
// Strip comments from pre/post, preserving whitespace
|
|
585
|
+
newNode.stripPrePost(newNode, 'pre');
|
|
586
|
+
newNode.stripPrePost(newNode, 'post');
|
|
587
|
+
return newNode;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* `preEval` takes the following steps, which are extended in subclasses:
|
|
591
|
+
* 1. Clone the node (if the source node is wanted/needed)
|
|
592
|
+
* 2. Set `preEvaluated` to true
|
|
593
|
+
* 3. pre-evaluate all children
|
|
594
|
+
* 4. Return the node
|
|
595
|
+
*
|
|
596
|
+
* Mostly this is overridden to resolve names before registering.
|
|
597
|
+
*
|
|
598
|
+
* @todo - Update preEval / eval to use static evaluation based on flags.
|
|
599
|
+
*/
|
|
600
|
+
preEval(context) {
|
|
601
|
+
if (!this.preEvaluated) {
|
|
602
|
+
let node = this.maybeClone(context);
|
|
603
|
+
node.preEvaluated = true;
|
|
604
|
+
// Note: Rules nodes handle index assignment for themselves and their children
|
|
605
|
+
// Other nodes will get indices assigned by their parent Rules
|
|
606
|
+
let out;
|
|
607
|
+
try {
|
|
608
|
+
out = node.forEachNode(n => n.preEval(context));
|
|
609
|
+
}
|
|
610
|
+
catch (error) {
|
|
611
|
+
throw error;
|
|
612
|
+
}
|
|
613
|
+
if (isThenable(out)) {
|
|
614
|
+
return out.then(() => node).catch((error) => {
|
|
615
|
+
throw error;
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
return node;
|
|
619
|
+
}
|
|
620
|
+
return this;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* This is the method all nodes will override.
|
|
624
|
+
* Individual nodes will specify / narrow return type
|
|
625
|
+
*
|
|
626
|
+
* By default, evals all children
|
|
627
|
+
*/
|
|
628
|
+
evalNode(context) {
|
|
629
|
+
let out = this.forEachNode((n) => {
|
|
630
|
+
return n.eval(context);
|
|
631
|
+
});
|
|
632
|
+
if (isThenable(out)) {
|
|
633
|
+
return out.then(() => {
|
|
634
|
+
return this;
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
return this;
|
|
638
|
+
}
|
|
639
|
+
static evalStatic(node, context) {
|
|
640
|
+
let preEvaluatedNode;
|
|
641
|
+
return pipe(() => {
|
|
642
|
+
if (!node.preEvaluated) {
|
|
643
|
+
return node.preEval(context);
|
|
644
|
+
}
|
|
645
|
+
return node;
|
|
646
|
+
}, (preEvald) => {
|
|
647
|
+
preEvaluatedNode = preEvald;
|
|
648
|
+
preEvaluatedNode.preEvaluated = true;
|
|
649
|
+
if (preEvald !== node) {
|
|
650
|
+
preEvaluatedNode.inherit(node);
|
|
651
|
+
}
|
|
652
|
+
if (!preEvaluatedNode.evaluated) {
|
|
653
|
+
return preEvaluatedNode.evalNode(context);
|
|
654
|
+
}
|
|
655
|
+
return preEvaluatedNode;
|
|
656
|
+
}, (evald) => {
|
|
657
|
+
evald.evaluated = true;
|
|
658
|
+
if (preEvaluatedNode !== evald) {
|
|
659
|
+
evald.inherit(preEvaluatedNode);
|
|
660
|
+
}
|
|
661
|
+
return evald;
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* @note - Make sure you don't call super.eval while evaluating a node. Call it indirectly
|
|
666
|
+
* from another node.
|
|
667
|
+
*/
|
|
668
|
+
eval(context) {
|
|
669
|
+
if (Object.getPrototypeOf(this).eval !== Node.prototype.eval) {
|
|
670
|
+
throw new Error('Do not call super.eval() from a subclass.');
|
|
671
|
+
}
|
|
672
|
+
return Node.evalStatic(this, context);
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* This is used when a Node will replace another node.
|
|
676
|
+
*/
|
|
677
|
+
inherit(node) {
|
|
678
|
+
/**
|
|
679
|
+
* Frozen nodes inherit the parent only if they don't have a parent yet.
|
|
680
|
+
*/
|
|
681
|
+
if (!this.frozen) {
|
|
682
|
+
this.parent = node.parent;
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
this.parent ??= node.parent;
|
|
686
|
+
}
|
|
687
|
+
this._location = node.location;
|
|
688
|
+
this._treeContext ??= node.treeContext;
|
|
689
|
+
/** Copy state exactly (not OR, to preserve removed flags) */
|
|
690
|
+
// Only sync F_VISIBLE flag, preserve all other flags
|
|
691
|
+
if (!node.hasFlag(F_VISIBLE)) {
|
|
692
|
+
this.removeFlag(F_VISIBLE);
|
|
693
|
+
}
|
|
694
|
+
// Preserve F_IMPLICIT_AMPERSAND so cloned selectors (e.g. after extend) keep invisible-ampersand
|
|
695
|
+
// handling in createProcessedSelector and valueOf() remains correct for exact extend matching.
|
|
696
|
+
if (node.hasFlag(F_IMPLICIT_AMPERSAND)) {
|
|
697
|
+
this.addFlag(F_IMPLICIT_AMPERSAND);
|
|
698
|
+
}
|
|
699
|
+
if (node.hasFlag(F_EXTENDED)) {
|
|
700
|
+
this.addFlag(F_EXTENDED);
|
|
701
|
+
}
|
|
702
|
+
if (node.hasFlag(F_EXTEND_TARGET)) {
|
|
703
|
+
this.addFlag(F_EXTEND_TARGET);
|
|
704
|
+
}
|
|
705
|
+
// Note that we need to create new arrays if we mutate pre/post later
|
|
706
|
+
this.pre ||= node.pre;
|
|
707
|
+
this.post ||= node.post;
|
|
708
|
+
this.sourceNode = node.sourceNode;
|
|
709
|
+
this.sourceParent ??= node.sourceParent;
|
|
710
|
+
// Preserve the generated flag when inheriting; never overwrite true with false
|
|
711
|
+
// (e.g. Ampersand.eval returns PseudoSelector with .generated true, then evalStatic
|
|
712
|
+
// calls PseudoSelector.inherit(Ampersand), which would otherwise overwrite with false)
|
|
713
|
+
this.generated = this.generated || node.generated;
|
|
714
|
+
/**
|
|
715
|
+
* If it's replacing a node that's evaluated, it should inherit the same index.
|
|
716
|
+
* Otherwise, it should be settable after cloning / copying.
|
|
717
|
+
*/
|
|
718
|
+
this.index ??= node.index;
|
|
719
|
+
return this;
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Represents the normalized string value of the node,
|
|
723
|
+
* for the purposes of comparison with other nodes,
|
|
724
|
+
* regardless of type.
|
|
725
|
+
*
|
|
726
|
+
* Derived nodes will override this with different
|
|
727
|
+
* normalization algorithms.
|
|
728
|
+
*/
|
|
729
|
+
valueOf() {
|
|
730
|
+
let value = this.value;
|
|
731
|
+
let type = typeof value;
|
|
732
|
+
if (primitives.includes(type)) {
|
|
733
|
+
return value;
|
|
734
|
+
}
|
|
735
|
+
let values = [...getValues(value)];
|
|
736
|
+
if (values.length === 1) {
|
|
737
|
+
return `${values[0]}`;
|
|
738
|
+
}
|
|
739
|
+
return values.join('');
|
|
740
|
+
}
|
|
741
|
+
processPrePost(key, defaultVal = '', options) {
|
|
742
|
+
options = getPrintOptions(options);
|
|
743
|
+
const w = options.writer;
|
|
744
|
+
const mark = w.mark();
|
|
745
|
+
let value = this[key];
|
|
746
|
+
if (value === undefined) {
|
|
747
|
+
if (defaultVal) {
|
|
748
|
+
w.add(defaultVal);
|
|
749
|
+
if (defaultVal === ' ') {
|
|
750
|
+
w.signalBoundaryIntent(key, 'explicit_space');
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return w.getSince(mark);
|
|
754
|
+
}
|
|
755
|
+
else if (value === 0) {
|
|
756
|
+
w.signalBoundaryIntent(key, 'explicit_none');
|
|
757
|
+
return '';
|
|
758
|
+
}
|
|
759
|
+
else if (value === 1) {
|
|
760
|
+
w.add(' ');
|
|
761
|
+
w.signalBoundaryIntent(key, 'explicit_space');
|
|
762
|
+
return w.getSince(mark);
|
|
763
|
+
}
|
|
764
|
+
else if (isArray(value)) {
|
|
765
|
+
// Handle Node[] array - call toString() on each node (they will emit into writer)
|
|
766
|
+
for (let node of value) {
|
|
767
|
+
if (node instanceof Node) {
|
|
768
|
+
node.toString(options);
|
|
769
|
+
}
|
|
770
|
+
else {
|
|
771
|
+
const s = String(node);
|
|
772
|
+
w.add(s);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
return w.getSince(mark);
|
|
776
|
+
}
|
|
777
|
+
else {
|
|
778
|
+
const s = String(value);
|
|
779
|
+
w.add(s);
|
|
780
|
+
return w.getSince(mark);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* This re-serializes the node, if needed. Will
|
|
785
|
+
* likely be over-ridden in some cases.
|
|
786
|
+
*
|
|
787
|
+
* Note that this is the "as-is" representation of the
|
|
788
|
+
* node, not the "evaluated" version.
|
|
789
|
+
*
|
|
790
|
+
* Note that the ToCssVisitor will be a little
|
|
791
|
+
* more sophisticated, as it will re-format
|
|
792
|
+
* to some extent by replacing newlines + spacing
|
|
793
|
+
* with the appropriate amount of whitespace.
|
|
794
|
+
*
|
|
795
|
+
* @note toString() will, by default, include pre/post
|
|
796
|
+
* white-space and comments, to make serialization
|
|
797
|
+
* easy.
|
|
798
|
+
*
|
|
799
|
+
* In almost all Node cases, this should not be overriden,
|
|
800
|
+
* and toTrimmedString() should be overridden instead.
|
|
801
|
+
*/
|
|
802
|
+
toString(options) {
|
|
803
|
+
if (!this.hasFlag(F_VISIBLE) && !this.fullRender) {
|
|
804
|
+
return '';
|
|
805
|
+
}
|
|
806
|
+
options = getPrintOptions(options);
|
|
807
|
+
const w = options.writer;
|
|
808
|
+
const mark = w.mark();
|
|
809
|
+
let pre = w.capture(() => this.processPrePost('pre', '', options));
|
|
810
|
+
const bodyStr = w.capture(() => this.toTrimmedString(options));
|
|
811
|
+
let post = w.capture(() => this.processPrePost('post', '', options));
|
|
812
|
+
let result = pre + bodyStr + post;
|
|
813
|
+
// Trim output if flag is set
|
|
814
|
+
w.add(result, this);
|
|
815
|
+
return w.getSince(mark);
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* The form of the node without pre/post comments and white-space
|
|
819
|
+
*
|
|
820
|
+
* @note - Internally, this still calls `toString()` on each value,
|
|
821
|
+
* so that the internal spacing of the node serialization is
|
|
822
|
+
* correct. This method just serializes a node without the outer
|
|
823
|
+
* pre/post nodes.
|
|
824
|
+
*/
|
|
825
|
+
toTrimmedString(options) {
|
|
826
|
+
options = getPrintOptions(options);
|
|
827
|
+
const w = options.writer;
|
|
828
|
+
const mark = w.mark();
|
|
829
|
+
for (let value of getValues(this.value)) {
|
|
830
|
+
if (value instanceof Node) {
|
|
831
|
+
value.toString(options);
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
const s = value === undefined ? '' : String(value);
|
|
835
|
+
if (s) {
|
|
836
|
+
w.add(s, this);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return w.getSince(mark);
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Individual node types will override this.
|
|
844
|
+
*
|
|
845
|
+
* This is just a default implementation.
|
|
846
|
+
* 0 = equal (==)
|
|
847
|
+
* 1 = greater than (>)
|
|
848
|
+
* -1 = less than (<)
|
|
849
|
+
* undefined = not comparable
|
|
850
|
+
*/
|
|
851
|
+
compare(b, context) {
|
|
852
|
+
let aVal = this.valueOf();
|
|
853
|
+
let bVal = b.valueOf();
|
|
854
|
+
if (aVal === bVal) {
|
|
855
|
+
return 0;
|
|
856
|
+
}
|
|
857
|
+
if (aVal === undefined || bVal === undefined) {
|
|
858
|
+
return undefined;
|
|
859
|
+
}
|
|
860
|
+
return aVal > bVal ? 1 : -1;
|
|
861
|
+
}
|
|
862
|
+
/** Overridden in index.ts to avoid circularity */
|
|
863
|
+
operate(b, op, context) {
|
|
864
|
+
return this;
|
|
865
|
+
}
|
|
866
|
+
static numericCompare(a, b) {
|
|
867
|
+
if (a === b) {
|
|
868
|
+
return 0;
|
|
869
|
+
}
|
|
870
|
+
else if (Math.abs(a - b) < Number.EPSILON) {
|
|
871
|
+
/** Close enough! Prevents floating point precision issues */
|
|
872
|
+
return 0;
|
|
873
|
+
}
|
|
874
|
+
else if (a > b) {
|
|
875
|
+
return 1;
|
|
876
|
+
}
|
|
877
|
+
else {
|
|
878
|
+
return -1;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
/** When converting Less/Sass to Jess, we'll switch this flag temporarily */
|
|
883
|
+
Node.prototype.fullRender = false;
|
|
884
|
+
//# sourceMappingURL=node-base.js.map
|