less 4.5.1 → 4.6.0
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/bin/lessc +37 -23
- package/dist/less.js +14497 -11745
- package/dist/less.min.js +4 -4
- package/dist/less.min.js.map +1 -1
- package/lib/less/constants.js +5 -7
- package/lib/less/contexts.js +71 -55
- package/lib/less/data/colors.js +150 -153
- package/lib/less/data/index.js +4 -7
- package/lib/less/data/unit-conversions.js +2 -5
- package/lib/less/default-options.js +36 -26
- package/lib/less/deprecation.js +67 -0
- package/lib/less/environment/abstract-file-manager.js +62 -50
- package/lib/less/environment/abstract-plugin-loader.js +69 -46
- package/lib/less/environment/environment-api.ts +21 -0
- package/lib/less/environment/environment.js +34 -30
- package/lib/less/environment/file-manager-api.ts +77 -0
- package/lib/less/functions/boolean.js +13 -13
- package/lib/less/functions/color-blending.js +39 -31
- package/lib/less/functions/color.js +153 -137
- package/lib/less/functions/data-uri.js +73 -64
- package/lib/less/functions/default.js +9 -11
- package/lib/less/functions/function-caller.js +35 -34
- package/lib/less/functions/function-registry.js +16 -17
- package/lib/less/functions/index.js +33 -33
- package/lib/less/functions/list.js +88 -75
- package/lib/less/functions/math-helper.js +8 -11
- package/lib/less/functions/math.js +21 -21
- package/lib/less/functions/number.js +42 -53
- package/lib/less/functions/string.js +18 -22
- package/lib/less/functions/style.js +21 -20
- package/lib/less/functions/svg.js +83 -82
- package/lib/less/functions/types.js +28 -32
- package/lib/less/import-manager.js +73 -64
- package/lib/less/index.js +65 -65
- package/lib/less/less-error.js +63 -45
- package/lib/less/logger.js +11 -14
- package/lib/less/parse-tree.js +52 -53
- package/lib/less/parse.js +44 -44
- package/lib/less/parser/parser-input.js +151 -113
- package/lib/less/parser/parser.js +864 -658
- package/lib/less/plugin-manager.js +57 -46
- package/lib/less/render.js +17 -23
- package/lib/less/source-map-builder.js +52 -43
- package/lib/less/source-map-output.js +56 -43
- package/lib/less/transform-tree.js +40 -30
- package/lib/less/tree/anonymous.js +52 -28
- package/lib/less/tree/assignment.js +44 -27
- package/lib/less/tree/atrule-syntax.js +4 -6
- package/lib/less/tree/atrule.js +247 -140
- package/lib/less/tree/attribute.js +55 -24
- package/lib/less/tree/call.js +70 -42
- package/lib/less/tree/color.js +194 -145
- package/lib/less/tree/combinator.js +31 -21
- package/lib/less/tree/comment.js +44 -23
- package/lib/less/tree/condition.js +61 -36
- package/lib/less/tree/container.js +90 -34
- package/lib/less/tree/debug-info.js +28 -15
- package/lib/less/tree/declaration.js +97 -52
- package/lib/less/tree/detached-ruleset.js +42 -24
- package/lib/less/tree/dimension.js +127 -71
- package/lib/less/tree/element.js +82 -52
- package/lib/less/tree/expression.js +75 -50
- package/lib/less/tree/extend.js +71 -42
- package/lib/less/tree/import.js +184 -110
- package/lib/less/tree/index.js +52 -81
- package/lib/less/tree/javascript.js +43 -32
- package/lib/less/tree/js-eval-node.js +46 -32
- package/lib/less/tree/keyword.js +25 -17
- package/lib/less/tree/media.js +77 -35
- package/lib/less/tree/merge-rules.js +47 -0
- package/lib/less/tree/mixin-call.js +181 -98
- package/lib/less/tree/mixin-definition.js +211 -117
- package/lib/less/tree/namespace-value.js +63 -44
- package/lib/less/tree/negative.js +34 -21
- package/lib/less/tree/nested-at-rule.js +149 -66
- package/lib/less/tree/node.js +225 -90
- package/lib/less/tree/operation.js +59 -34
- package/lib/less/tree/paren.js +34 -17
- package/lib/less/tree/property.js +66 -35
- package/lib/less/tree/query-in-parens.js +52 -60
- package/lib/less/tree/quoted.js +93 -44
- package/lib/less/tree/ruleset.js +632 -318
- package/lib/less/tree/selector.js +151 -77
- package/lib/less/tree/unicode-descriptor.js +14 -12
- package/lib/less/tree/unit.js +111 -63
- package/lib/less/tree/url.js +62 -38
- package/lib/less/tree/value.js +50 -34
- package/lib/less/tree/variable-call.js +47 -30
- package/lib/less/tree/variable.js +53 -31
- package/lib/less/utils.js +44 -47
- package/lib/less/visitors/extend-visitor.js +233 -172
- package/lib/less/visitors/import-sequencer.js +24 -24
- package/lib/less/visitors/import-visitor.js +62 -52
- package/lib/less/visitors/index.js +14 -17
- package/lib/less/visitors/join-selector-visitor.js +40 -37
- package/lib/less/visitors/set-tree-visibility-visitor.js +32 -18
- package/lib/less/visitors/to-css-visitor.js +135 -128
- package/lib/less/visitors/visitor.js +60 -45
- package/lib/less-browser/add-default-options.js +23 -13
- package/lib/less-browser/bootstrap.js +23 -17
- package/lib/less-browser/browser.js +24 -21
- package/lib/less-browser/cache.js +17 -19
- package/lib/less-browser/error-reporting.js +52 -44
- package/lib/less-browser/file-manager.js +52 -42
- package/lib/less-browser/image-size.js +12 -12
- package/lib/less-browser/index.js +131 -105
- package/lib/less-browser/log-listener.js +30 -31
- package/lib/less-browser/plugin-loader.js +10 -10
- package/lib/less-browser/utils.js +19 -21
- package/lib/less-node/environment.js +32 -8
- package/lib/less-node/file-manager.js +62 -45
- package/lib/less-node/fs.js +11 -8
- package/lib/less-node/image-size.js +40 -31
- package/lib/less-node/index.js +28 -19
- package/lib/less-node/lessc-helper.js +20 -21
- package/lib/less-node/plugin-loader.js +35 -27
- package/lib/less-node/url-file-manager.js +33 -31
- package/package.json +25 -18
- package/.eslintignore +0 -6
- package/.eslintrc.js +0 -63
- package/Gruntfile.js +0 -403
- package/bower.json +0 -22
- package/lib/less/constants.js.map +0 -1
- package/lib/less/contexts.js.map +0 -1
- package/lib/less/data/colors.js.map +0 -1
- package/lib/less/data/index.js.map +0 -1
- package/lib/less/data/unit-conversions.js.map +0 -1
- package/lib/less/default-options.js.map +0 -1
- package/lib/less/environment/abstract-file-manager.js.map +0 -1
- package/lib/less/environment/abstract-plugin-loader.js.map +0 -1
- package/lib/less/environment/environment-api.js +0 -3
- package/lib/less/environment/environment-api.js.map +0 -1
- package/lib/less/environment/environment.js.map +0 -1
- package/lib/less/environment/file-manager-api.js +0 -3
- package/lib/less/environment/file-manager-api.js.map +0 -1
- package/lib/less/functions/boolean.js.map +0 -1
- package/lib/less/functions/color-blending.js.map +0 -1
- package/lib/less/functions/color.js.map +0 -1
- package/lib/less/functions/data-uri.js.map +0 -1
- package/lib/less/functions/default.js.map +0 -1
- package/lib/less/functions/function-caller.js.map +0 -1
- package/lib/less/functions/function-registry.js.map +0 -1
- package/lib/less/functions/index.js.map +0 -1
- package/lib/less/functions/list.js.map +0 -1
- package/lib/less/functions/math-helper.js.map +0 -1
- package/lib/less/functions/math.js.map +0 -1
- package/lib/less/functions/number.js.map +0 -1
- package/lib/less/functions/string.js.map +0 -1
- package/lib/less/functions/style.js.map +0 -1
- package/lib/less/functions/svg.js.map +0 -1
- package/lib/less/functions/types.js.map +0 -1
- package/lib/less/import-manager.js.map +0 -1
- package/lib/less/index.js.map +0 -1
- package/lib/less/less-error.js.map +0 -1
- package/lib/less/logger.js.map +0 -1
- package/lib/less/parse-tree.js.map +0 -1
- package/lib/less/parse.js.map +0 -1
- package/lib/less/parser/parser-input.js.map +0 -1
- package/lib/less/parser/parser.js.map +0 -1
- package/lib/less/plugin-manager.js.map +0 -1
- package/lib/less/render.js.map +0 -1
- package/lib/less/source-map-builder.js.map +0 -1
- package/lib/less/source-map-output.js.map +0 -1
- package/lib/less/transform-tree.js.map +0 -1
- package/lib/less/tree/anonymous.js.map +0 -1
- package/lib/less/tree/assignment.js.map +0 -1
- package/lib/less/tree/atrule-syntax.js.map +0 -1
- package/lib/less/tree/atrule.js.map +0 -1
- package/lib/less/tree/attribute.js.map +0 -1
- package/lib/less/tree/call.js.map +0 -1
- package/lib/less/tree/color.js.map +0 -1
- package/lib/less/tree/combinator.js.map +0 -1
- package/lib/less/tree/comment.js.map +0 -1
- package/lib/less/tree/condition.js.map +0 -1
- package/lib/less/tree/container.js.map +0 -1
- package/lib/less/tree/debug-info.js.map +0 -1
- package/lib/less/tree/declaration.js.map +0 -1
- package/lib/less/tree/detached-ruleset.js.map +0 -1
- package/lib/less/tree/dimension.js.map +0 -1
- package/lib/less/tree/element.js.map +0 -1
- package/lib/less/tree/expression.js.map +0 -1
- package/lib/less/tree/extend.js.map +0 -1
- package/lib/less/tree/import.js.map +0 -1
- package/lib/less/tree/index.js.map +0 -1
- package/lib/less/tree/javascript.js.map +0 -1
- package/lib/less/tree/js-eval-node.js.map +0 -1
- package/lib/less/tree/keyword.js.map +0 -1
- package/lib/less/tree/media.js.map +0 -1
- package/lib/less/tree/mixin-call.js.map +0 -1
- package/lib/less/tree/mixin-definition.js.map +0 -1
- package/lib/less/tree/namespace-value.js.map +0 -1
- package/lib/less/tree/negative.js.map +0 -1
- package/lib/less/tree/nested-at-rule.js.map +0 -1
- package/lib/less/tree/node.js.map +0 -1
- package/lib/less/tree/operation.js.map +0 -1
- package/lib/less/tree/paren.js.map +0 -1
- package/lib/less/tree/property.js.map +0 -1
- package/lib/less/tree/query-in-parens.js.map +0 -1
- package/lib/less/tree/quoted.js.map +0 -1
- package/lib/less/tree/ruleset.js.map +0 -1
- package/lib/less/tree/selector.js.map +0 -1
- package/lib/less/tree/unicode-descriptor.js.map +0 -1
- package/lib/less/tree/unit.js.map +0 -1
- package/lib/less/tree/url.js.map +0 -1
- package/lib/less/tree/value.js.map +0 -1
- package/lib/less/tree/variable-call.js.map +0 -1
- package/lib/less/tree/variable.js.map +0 -1
- package/lib/less/utils.js.map +0 -1
- package/lib/less/visitors/extend-visitor.js.map +0 -1
- package/lib/less/visitors/import-sequencer.js.map +0 -1
- package/lib/less/visitors/import-visitor.js.map +0 -1
- package/lib/less/visitors/index.js.map +0 -1
- package/lib/less/visitors/join-selector-visitor.js.map +0 -1
- package/lib/less/visitors/set-tree-visibility-visitor.js.map +0 -1
- package/lib/less/visitors/to-css-visitor.js.map +0 -1
- package/lib/less/visitors/visitor.js.map +0 -1
- package/lib/less-browser/add-default-options.js.map +0 -1
- package/lib/less-browser/bootstrap.js.map +0 -1
- package/lib/less-browser/browser.js.map +0 -1
- package/lib/less-browser/cache.js.map +0 -1
- package/lib/less-browser/error-reporting.js.map +0 -1
- package/lib/less-browser/file-manager.js.map +0 -1
- package/lib/less-browser/image-size.js.map +0 -1
- package/lib/less-browser/index.js.map +0 -1
- package/lib/less-browser/log-listener.js.map +0 -1
- package/lib/less-browser/plugin-loader.js.map +0 -1
- package/lib/less-browser/utils.js.map +0 -1
- package/lib/less-node/environment.js.map +0 -1
- package/lib/less-node/file-manager.js.map +0 -1
- package/lib/less-node/fs.js.map +0 -1
- package/lib/less-node/image-size.js.map +0 -1
- package/lib/less-node/index.js.map +0 -1
- package/lib/less-node/lessc-helper.js.map +0 -1
- package/lib/less-node/plugin-loader.js.map +0 -1
- package/lib/less-node/url-file-manager.js.map +0 -1
- package/scripts/coverage-lines.js +0 -207
- package/scripts/coverage-report.js +0 -158
- package/scripts/postinstall.js +0 -61
- package/test/.eslintrc.json +0 -9
- package/test/README.md +0 -3
- package/test/browser/common.js +0 -251
- package/test/browser/css/global-vars/simple.css +0 -3
- package/test/browser/css/modify-vars/simple.css +0 -8
- package/test/browser/css/plugin/plugin.css +0 -3
- package/test/browser/css/postProcessor/postProcessor.css +0 -4
- package/test/browser/css/relative-urls/urls.css +0 -36
- package/test/browser/css/rewrite-urls/urls.css +0 -36
- package/test/browser/css/rootpath/urls.css +0 -35
- package/test/browser/css/rootpath-relative/urls.css +0 -35
- package/test/browser/css/rootpath-rewrite-urls/urls.css +0 -35
- package/test/browser/css/urls.css +0 -54
- package/test/browser/generator/benchmark.config.js +0 -50
- package/test/browser/generator/generate.js +0 -78
- package/test/browser/generator/runner.config.js +0 -184
- package/test/browser/generator/runner.js +0 -2
- package/test/browser/generator/template.js +0 -104
- package/test/browser/generator/utils.js +0 -14
- package/test/browser/less/console-errors/test-error.less +0 -3
- package/test/browser/less/console-errors/test-error.txt +0 -2
- package/test/browser/less/errors/image-height-error.less +0 -3
- package/test/browser/less/errors/image-height-error.txt +0 -4
- package/test/browser/less/errors/image-size-error.less +0 -3
- package/test/browser/less/errors/image-size-error.txt +0 -4
- package/test/browser/less/errors/image-width-error.less +0 -3
- package/test/browser/less/errors/image-width-error.txt +0 -4
- package/test/browser/less/global-vars/simple.less +0 -3
- package/test/browser/less/imports/urls.less +0 -4
- package/test/browser/less/imports/urls2.less +0 -4
- package/test/browser/less/modify-vars/imports/simple2.less +0 -4
- package/test/browser/less/modify-vars/simple.less +0 -8
- package/test/browser/less/nested-gradient-with-svg-gradient/mixin-consumer.less +0 -5
- package/test/browser/less/nested-gradient-with-svg-gradient/svg-gradient-mixin.less +0 -15
- package/test/browser/less/plugin/plugin.js +0 -4
- package/test/browser/less/plugin/plugin.less +0 -4
- package/test/browser/less/postProcessor/postProcessor.less +0 -4
- package/test/browser/less/relative-urls/urls.less +0 -34
- package/test/browser/less/rewrite-urls/urls.less +0 -34
- package/test/browser/less/rootpath/urls.less +0 -33
- package/test/browser/less/rootpath-relative/urls.less +0 -33
- package/test/browser/less/rootpath-rewrite-urls/urls.less +0 -33
- package/test/browser/less/urls.less +0 -62
- package/test/browser/runner-VisitorPlugin-options.js +0 -3
- package/test/browser/runner-VisitorPlugin.js +0 -3
- package/test/browser/runner-browser-options.js +0 -51
- package/test/browser/runner-browser-spec.js +0 -12
- package/test/browser/runner-console-errors.js +0 -5
- package/test/browser/runner-errors-options.js +0 -6
- package/test/browser/runner-errors-spec.js +0 -3
- package/test/browser/runner-filemanagerPlugin-options.js +0 -5
- package/test/browser/runner-filemanagerPlugin.js +0 -3
- package/test/browser/runner-global-vars-options.js +0 -7
- package/test/browser/runner-global-vars-spec.js +0 -3
- package/test/browser/runner-main-options.js +0 -17
- package/test/browser/runner-main-spec.js +0 -7
- package/test/browser/runner-modify-vars-options.js +0 -5
- package/test/browser/runner-modify-vars-spec.js +0 -33
- package/test/browser/runner-no-js-errors-options.js +0 -4
- package/test/browser/runner-no-js-errors-spec.js +0 -3
- package/test/browser/runner-postProcessorPlugin-options.js +0 -3
- package/test/browser/runner-postProcessorPlugin.js +0 -3
- package/test/browser/runner-preProcessorPlugin-options.js +0 -3
- package/test/browser/runner-preProcessorPlugin.js +0 -3
- package/test/browser/runner-production-options.js +0 -3
- package/test/browser/runner-production-spec.js +0 -5
- package/test/browser/runner-relative-urls-options.js +0 -3
- package/test/browser/runner-relative-urls-spec.js +0 -3
- package/test/browser/runner-rewrite-urls-options.js +0 -3
- package/test/browser/runner-rewrite-urls-spec.js +0 -3
- package/test/browser/runner-rootpath-options.js +0 -3
- package/test/browser/runner-rootpath-relative-options.js +0 -4
- package/test/browser/runner-rootpath-relative-spec.js +0 -3
- package/test/browser/runner-rootpath-rewrite-urls-options.js +0 -4
- package/test/browser/runner-rootpath-rewrite-urls-spec.js +0 -3
- package/test/browser/runner-rootpath-spec.js +0 -3
- package/test/browser/runner-strict-units-options.js +0 -5
- package/test/browser/runner-strict-units-spec.js +0 -3
- package/test/index.js +0 -307
- package/test/less-test.js +0 -984
- package/test/mocha-playwright/runner.js +0 -210
- package/test/modify-vars.js +0 -28
- package/test/plugins/filemanager/index.js +0 -19
- package/test/plugins/postprocess/index.js +0 -14
- package/test/plugins/preprocess/index.js +0 -19
- package/test/plugins/visitor/index.js +0 -24
- package/test/sourcemaps/basic.json +0 -1
- package/test/sourcemaps/comprehensive.json +0 -1
- package/test/sourcemaps/custom-props.json +0 -1
- package/test/sourcemaps/index.html +0 -17
- package/test/sourcemaps/sourcemaps-basepath.json +0 -1
- package/test/sourcemaps/sourcemaps-include-source.json +0 -1
- package/test/sourcemaps/sourcemaps-rootpath.json +0 -1
- package/test/sourcemaps/sourcemaps-url.json +0 -1
- package/test/sourcemaps-disable-annotation/basic.json +0 -1
- package/test/sourcemaps-variable-selector/basic.json +0 -1
- package/test/test-es6.ts +0 -17
- package/test.less +0 -1
- package/tsconfig.build.json +0 -7
- package/tsconfig.json +0 -21
package/lib/less/tree/ruleset.js
CHANGED
|
@@ -1,63 +1,129 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @import { EvalContext, CSSOutput, TreeVisitor, FileInfo, VisibilityInfo } from './node.js' */
|
|
3
|
+
/** @import { FunctionRegistry } from './nested-at-rule.js' */
|
|
4
|
+
import Node from './node.js';
|
|
5
|
+
import Declaration from './declaration.js';
|
|
6
|
+
import Keyword from './keyword.js';
|
|
7
|
+
import Comment from './comment.js';
|
|
8
|
+
import Paren from './paren.js';
|
|
9
|
+
import Selector from './selector.js';
|
|
10
|
+
import Element from './element.js';
|
|
11
|
+
import Anonymous from './anonymous.js';
|
|
12
|
+
import contexts from '../contexts.js';
|
|
13
|
+
import globalFunctionRegistry from '../functions/function-registry.js';
|
|
14
|
+
import defaultFunc from '../functions/default.js';
|
|
15
|
+
import getDebugInfo from './debug-info.js';
|
|
16
|
+
import * as utils from '../utils.js';
|
|
17
|
+
import Parser from '../parser/parser.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {Node & {
|
|
21
|
+
* rules?: Node[],
|
|
22
|
+
* selectors?: Selector[],
|
|
23
|
+
* root?: boolean,
|
|
24
|
+
* firstRoot?: boolean,
|
|
25
|
+
* allowImports?: boolean,
|
|
26
|
+
* functionRegistry?: FunctionRegistry,
|
|
27
|
+
* originalRuleset?: Node,
|
|
28
|
+
* debugInfo?: { lineNumber: number, fileName: string },
|
|
29
|
+
* evalFirst?: boolean,
|
|
30
|
+
* isRuleset?: boolean,
|
|
31
|
+
* isCharset?: () => boolean,
|
|
32
|
+
* merge?: boolean | string,
|
|
33
|
+
* multiMedia?: boolean,
|
|
34
|
+
* parse?: { context: EvalContext, importManager: object },
|
|
35
|
+
* bubbleSelectors?: (selectors: Selector[]) => void
|
|
36
|
+
* }} RuleNode
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
class Ruleset extends Node {
|
|
40
|
+
get type() { return 'Ruleset'; }
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {Selector[] | null} selectors
|
|
44
|
+
* @param {Node[] | null} rules
|
|
45
|
+
* @param {boolean} [strictImports]
|
|
46
|
+
* @param {VisibilityInfo} [visibilityInfo]
|
|
47
|
+
*/
|
|
48
|
+
constructor(selectors, rules, strictImports, visibilityInfo) {
|
|
49
|
+
super();
|
|
50
|
+
/** @type {Selector[] | null} */
|
|
51
|
+
this.selectors = selectors;
|
|
52
|
+
/** @type {Node[] | null} */
|
|
53
|
+
this.rules = rules;
|
|
54
|
+
/** @type {Object<string, { rule: Node, path: Node[] }[]>} */
|
|
55
|
+
this._lookups = {};
|
|
56
|
+
/** @type {Object<string, Declaration> | null} */
|
|
57
|
+
this._variables = null;
|
|
58
|
+
/** @type {Object<string, Declaration[]> | null} */
|
|
59
|
+
this._properties = null;
|
|
60
|
+
/** @type {boolean | undefined} */
|
|
61
|
+
this.strictImports = strictImports;
|
|
62
|
+
this.copyVisibilityInfo(visibilityInfo);
|
|
63
|
+
this.allowRoot = true;
|
|
64
|
+
/** @type {boolean} */
|
|
65
|
+
this.isRuleset = true;
|
|
66
|
+
|
|
67
|
+
/** @type {boolean | undefined} */
|
|
68
|
+
this.root = undefined;
|
|
69
|
+
/** @type {boolean | undefined} */
|
|
70
|
+
this.firstRoot = undefined;
|
|
71
|
+
/** @type {boolean | undefined} */
|
|
72
|
+
this.allowImports = undefined;
|
|
73
|
+
/** @type {FunctionRegistry | undefined} */
|
|
74
|
+
this.functionRegistry = undefined;
|
|
75
|
+
/** @type {Node | undefined} */
|
|
76
|
+
this.originalRuleset = undefined;
|
|
77
|
+
/** @type {{ lineNumber: number, fileName: string } | undefined} */
|
|
78
|
+
this.debugInfo = undefined;
|
|
79
|
+
/** @type {Selector[][] | undefined} */
|
|
80
|
+
this.paths = undefined;
|
|
81
|
+
/** @type {Ruleset[] | null | undefined} */
|
|
82
|
+
this._rulesets = undefined;
|
|
83
|
+
/** @type {boolean | undefined} */
|
|
84
|
+
this.evalFirst = undefined;
|
|
85
|
+
this.setParent(this.selectors, this);
|
|
86
|
+
this.setParent(this.rules, this);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
isRulesetLike() { return true; }
|
|
90
|
+
|
|
91
|
+
/** @param {TreeVisitor} visitor */
|
|
92
|
+
accept(visitor) {
|
|
35
93
|
if (this.paths) {
|
|
36
|
-
this.paths = visitor.visitArray(this.paths, true);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
this.selectors = visitor.visitArray(this.selectors);
|
|
94
|
+
this.paths = /** @type {Selector[][]} */ (/** @type {unknown} */ (visitor.visitArray(/** @type {Node[]} */ (/** @type {unknown} */ (this.paths)), true)));
|
|
95
|
+
} else if (this.selectors) {
|
|
96
|
+
this.selectors = /** @type {Selector[]} */ (visitor.visitArray(this.selectors));
|
|
40
97
|
}
|
|
41
98
|
if (this.rules && this.rules.length) {
|
|
42
99
|
this.rules = visitor.visitArray(this.rules);
|
|
43
100
|
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** @param {EvalContext} context */
|
|
104
|
+
eval(context) {
|
|
105
|
+
/** @type {Selector[] | undefined} */
|
|
106
|
+
let selectors;
|
|
107
|
+
/** @type {number} */
|
|
108
|
+
let selCnt;
|
|
109
|
+
/** @type {Selector} */
|
|
110
|
+
let selector;
|
|
111
|
+
/** @type {number} */
|
|
112
|
+
let i;
|
|
113
|
+
/** @type {boolean | undefined} */
|
|
114
|
+
let hasVariable;
|
|
115
|
+
let hasOnePassingSelector = false;
|
|
116
|
+
|
|
52
117
|
if (this.selectors && (selCnt = this.selectors.length)) {
|
|
53
118
|
selectors = new Array(selCnt);
|
|
54
|
-
|
|
119
|
+
defaultFunc.error({
|
|
55
120
|
type: 'Syntax',
|
|
56
121
|
message: 'it is currently only allowed in parametric mixin guards,'
|
|
57
122
|
});
|
|
123
|
+
|
|
58
124
|
for (i = 0; i < selCnt; i++) {
|
|
59
|
-
selector = this.selectors[i].eval(context);
|
|
60
|
-
for (
|
|
125
|
+
selector = /** @type {Selector} */ (this.selectors[i].eval(context));
|
|
126
|
+
for (let j = 0; j < selector.elements.length; j++) {
|
|
61
127
|
if (selector.elements[j].isVariable) {
|
|
62
128
|
hasVariable = true;
|
|
63
129
|
break;
|
|
@@ -68,112 +134,126 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
68
134
|
hasOnePassingSelector = true;
|
|
69
135
|
}
|
|
70
136
|
}
|
|
137
|
+
|
|
71
138
|
if (hasVariable) {
|
|
72
|
-
|
|
139
|
+
const toParseSelectors = new Array(selCnt);
|
|
73
140
|
for (i = 0; i < selCnt; i++) {
|
|
74
141
|
selector = selectors[i];
|
|
75
142
|
toParseSelectors[i] = selector.toCSS(context);
|
|
76
143
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
new
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
144
|
+
const startingIndex = selectors[0].getIndex();
|
|
145
|
+
const selectorFileInfo = selectors[0].fileInfo();
|
|
146
|
+
new (/** @type {new (...args: [EvalContext, object, FileInfo, number]) => { parseNode: Function }} */ (/** @type {unknown} */ (Parser)))(context, /** @type {{ context: EvalContext, importManager: object }} */ (this.parse).importManager, selectorFileInfo, startingIndex).parseNode(
|
|
147
|
+
toParseSelectors.join(','),
|
|
148
|
+
['selectors'],
|
|
149
|
+
function(/** @type {Error | null} */ err, /** @type {Node[]} */ result) {
|
|
150
|
+
if (result) {
|
|
151
|
+
selectors = /** @type {Selector[]} */ (utils.flattenArray(result));
|
|
152
|
+
}
|
|
153
|
+
});
|
|
84
154
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
else {
|
|
155
|
+
|
|
156
|
+
defaultFunc.reset();
|
|
157
|
+
} else {
|
|
88
158
|
hasOnePassingSelector = true;
|
|
89
159
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
160
|
+
|
|
161
|
+
let rules = this.rules ? utils.copyArray(this.rules) : null;
|
|
162
|
+
const ruleset = new Ruleset(selectors, rules, this.strictImports, this.visibilityInfo());
|
|
163
|
+
/** @type {Node} */
|
|
164
|
+
let rule;
|
|
165
|
+
/** @type {Node} */
|
|
166
|
+
let subRule;
|
|
167
|
+
|
|
94
168
|
ruleset.originalRuleset = this;
|
|
95
169
|
ruleset.root = this.root;
|
|
96
170
|
ruleset.firstRoot = this.firstRoot;
|
|
97
171
|
ruleset.allowImports = this.allowImports;
|
|
172
|
+
|
|
98
173
|
if (this.debugInfo) {
|
|
99
174
|
ruleset.debugInfo = this.debugInfo;
|
|
100
175
|
}
|
|
176
|
+
|
|
101
177
|
if (!hasOnePassingSelector) {
|
|
102
|
-
rules.length = 0;
|
|
178
|
+
/** @type {Node[]} */ (rules).length = 0;
|
|
103
179
|
}
|
|
180
|
+
|
|
181
|
+
// push the current ruleset to the frames stack
|
|
182
|
+
const ctxFrames = context.frames;
|
|
183
|
+
|
|
104
184
|
// inherit a function registry from the frames stack when possible;
|
|
105
185
|
// otherwise from the global registry
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return found;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return function_registry_1.default;
|
|
117
|
-
}(context.frames)).inherit();
|
|
118
|
-
// push the current ruleset to the frames stack
|
|
119
|
-
var ctxFrames = context.frames;
|
|
186
|
+
/** @type {FunctionRegistry | undefined} */
|
|
187
|
+
let foundRegistry;
|
|
188
|
+
for (let fi = 0, fn = ctxFrames.length; fi !== fn; ++fi) {
|
|
189
|
+
foundRegistry = /** @type {RuleNode} */ (ctxFrames[fi]).functionRegistry;
|
|
190
|
+
if (foundRegistry) { break; }
|
|
191
|
+
}
|
|
192
|
+
ruleset.functionRegistry = (foundRegistry || globalFunctionRegistry).inherit();
|
|
120
193
|
ctxFrames.unshift(ruleset);
|
|
194
|
+
|
|
121
195
|
// currrent selectors
|
|
122
|
-
|
|
196
|
+
/** @type {Selector[][] | undefined} */
|
|
197
|
+
let ctxSelectors = /** @type {EvalContext & { selectors?: Selector[][] }} */ (context).selectors;
|
|
123
198
|
if (!ctxSelectors) {
|
|
124
|
-
context.selectors = ctxSelectors = [];
|
|
199
|
+
/** @type {EvalContext & { selectors?: Selector[][] }} */ (context).selectors = ctxSelectors = [];
|
|
125
200
|
}
|
|
126
201
|
ctxSelectors.unshift(this.selectors);
|
|
202
|
+
|
|
127
203
|
// Evaluate imports
|
|
128
204
|
if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) {
|
|
129
205
|
ruleset.evalImports(context);
|
|
130
206
|
}
|
|
207
|
+
|
|
131
208
|
// Store the frames around mixin definitions,
|
|
132
209
|
// so they can be evaluated like closures when the time comes.
|
|
133
|
-
|
|
210
|
+
const rsRules = /** @type {Node[]} */ (ruleset.rules);
|
|
134
211
|
for (i = 0; (rule = rsRules[i]); i++) {
|
|
135
|
-
if (rule.evalFirst) {
|
|
212
|
+
if (/** @type {RuleNode} */ (rule).evalFirst) {
|
|
136
213
|
rsRules[i] = rule.eval(context);
|
|
137
214
|
}
|
|
138
215
|
}
|
|
139
|
-
|
|
216
|
+
|
|
217
|
+
const mediaBlockCount = (context.mediaBlocks && context.mediaBlocks.length) || 0;
|
|
218
|
+
|
|
140
219
|
// Evaluate mixin calls.
|
|
141
220
|
for (i = 0; (rule = rsRules[i]); i++) {
|
|
142
221
|
if (rule.type === 'MixinCall') {
|
|
143
222
|
/* jshint loopfunc:true */
|
|
144
|
-
rules = rule.eval(context).filter(function
|
|
145
|
-
if ((r instanceof
|
|
223
|
+
rules = /** @type {Node[]} */ (/** @type {unknown} */ (rule.eval(context))).filter(function(/** @type {Node & { variable?: boolean }} */ r) {
|
|
224
|
+
if ((r instanceof Declaration) && r.variable) {
|
|
146
225
|
// do not pollute the scope if the variable is
|
|
147
226
|
// already there. consider returning false here
|
|
148
227
|
// but we need a way to "return" variable from mixins
|
|
149
|
-
return !(ruleset.variable(r.name));
|
|
228
|
+
return !(ruleset.variable(/** @type {string} */ (r.name)));
|
|
150
229
|
}
|
|
151
230
|
return true;
|
|
152
231
|
});
|
|
153
|
-
rsRules.splice.apply(rsRules, [i, 1].concat(rules));
|
|
232
|
+
rsRules.splice.apply(rsRules, /** @type {[number, number, ...Node[]]} */ ([i, 1].concat(rules)));
|
|
154
233
|
i += rules.length - 1;
|
|
155
234
|
ruleset.resetCache();
|
|
156
|
-
}
|
|
157
|
-
else if (rule.type === 'VariableCall') {
|
|
235
|
+
} else if (rule.type === 'VariableCall') {
|
|
158
236
|
/* jshint loopfunc:true */
|
|
159
|
-
rules = rule.eval(context).rules.filter(function
|
|
160
|
-
if ((r instanceof
|
|
237
|
+
rules = /** @type {Node[]} */ (/** @type {RuleNode} */ (rule.eval(context)).rules).filter(function(/** @type {Node & { variable?: boolean }} */ r) {
|
|
238
|
+
if ((r instanceof Declaration) && r.variable) {
|
|
161
239
|
// do not pollute the scope at all
|
|
162
240
|
return false;
|
|
163
241
|
}
|
|
164
242
|
return true;
|
|
165
243
|
});
|
|
166
|
-
rsRules.splice.apply(rsRules, [i, 1].concat(rules));
|
|
244
|
+
rsRules.splice.apply(rsRules, /** @type {[number, number, ...Node[]]} */ ([i, 1].concat(rules)));
|
|
167
245
|
i += rules.length - 1;
|
|
168
246
|
ruleset.resetCache();
|
|
169
247
|
}
|
|
170
248
|
}
|
|
249
|
+
|
|
171
250
|
// Evaluate everything else
|
|
172
251
|
for (i = 0; (rule = rsRules[i]); i++) {
|
|
173
|
-
if (
|
|
252
|
+
if (!/** @type {RuleNode} */ (rule).evalFirst) {
|
|
174
253
|
rsRules[i] = rule = rule.eval ? rule.eval(context) : rule;
|
|
175
254
|
}
|
|
176
255
|
}
|
|
256
|
+
|
|
177
257
|
// Evaluate everything else
|
|
178
258
|
for (i = 0; (rule = rsRules[i]); i++) {
|
|
179
259
|
// for rulesets, check if it is a css guard and can be removed
|
|
@@ -181,10 +261,11 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
181
261
|
// check if it can be folded in (e.g. & where)
|
|
182
262
|
if (rule.selectors[0] && rule.selectors[0].isJustParentSelector()) {
|
|
183
263
|
rsRules.splice(i--, 1);
|
|
184
|
-
|
|
185
|
-
|
|
264
|
+
|
|
265
|
+
for (let j = 0; (subRule = rule.rules[j]); j++) {
|
|
266
|
+
if (subRule instanceof Node) {
|
|
186
267
|
subRule.copyVisibilityInfo(rule.visibilityInfo());
|
|
187
|
-
if (!(subRule instanceof
|
|
268
|
+
if (!(subRule instanceof Declaration) || !subRule.variable) {
|
|
188
269
|
rsRules.splice(++i, 0, subRule);
|
|
189
270
|
}
|
|
190
271
|
}
|
|
@@ -192,84 +273,100 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
192
273
|
}
|
|
193
274
|
}
|
|
194
275
|
}
|
|
276
|
+
|
|
195
277
|
// Pop the stack
|
|
196
278
|
ctxFrames.shift();
|
|
197
279
|
ctxSelectors.shift();
|
|
280
|
+
|
|
198
281
|
if (context.mediaBlocks) {
|
|
199
282
|
for (i = mediaBlockCount; i < context.mediaBlocks.length; i++) {
|
|
200
|
-
context.mediaBlocks[i].bubbleSelectors(selectors);
|
|
283
|
+
/** @type {RuleNode} */ (context.mediaBlocks[i]).bubbleSelectors(selectors);
|
|
201
284
|
}
|
|
202
285
|
}
|
|
286
|
+
|
|
203
287
|
return ruleset;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** @param {EvalContext} context */
|
|
291
|
+
evalImports(context) {
|
|
292
|
+
const rules = this.rules;
|
|
293
|
+
/** @type {number} */
|
|
294
|
+
let i;
|
|
295
|
+
/** @type {Node | Node[]} */
|
|
296
|
+
let importRules;
|
|
297
|
+
if (!rules) { return; }
|
|
298
|
+
|
|
212
299
|
for (i = 0; i < rules.length; i++) {
|
|
213
300
|
if (rules[i].type === 'Import') {
|
|
214
301
|
importRules = rules[i].eval(context);
|
|
215
|
-
if (importRules && (importRules.length || importRules.length === 0)) {
|
|
216
|
-
|
|
217
|
-
i
|
|
218
|
-
|
|
219
|
-
else {
|
|
302
|
+
if (importRules && (/** @type {Node[]} */ (/** @type {unknown} */ (importRules)).length || /** @type {Node[]} */ (/** @type {unknown} */ (importRules)).length === 0)) {
|
|
303
|
+
const importArr = /** @type {Node[]} */ (/** @type {unknown} */ (importRules));
|
|
304
|
+
rules.splice(i, 1, ...importArr);
|
|
305
|
+
i += importArr.length - 1;
|
|
306
|
+
} else {
|
|
220
307
|
rules.splice(i, 1, importRules);
|
|
221
308
|
}
|
|
222
309
|
this.resetCache();
|
|
223
310
|
}
|
|
224
311
|
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
makeImportant() {
|
|
315
|
+
const result = new Ruleset(this.selectors, /** @type {Node[]} */ (this.rules).map(function (/** @type {Node & { makeImportant?: () => Node }} */ r) {
|
|
228
316
|
if (r.makeImportant) {
|
|
229
317
|
return r.makeImportant();
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
318
|
+
} else {
|
|
232
319
|
return r;
|
|
233
320
|
}
|
|
234
321
|
}), this.strictImports, this.visibilityInfo());
|
|
322
|
+
|
|
235
323
|
return result;
|
|
236
|
-
}
|
|
237
|
-
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** @param {Node[] | object[] | null} [args] */
|
|
327
|
+
matchArgs(args) {
|
|
238
328
|
return !args || args.length === 0;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* @param {Node[] | object[] | null} args
|
|
333
|
+
* @param {EvalContext} context
|
|
334
|
+
*/
|
|
335
|
+
matchCondition(args, context) {
|
|
336
|
+
const lastSelector = /** @type {Selector[]} */ (this.selectors)[/** @type {Selector[]} */ (this.selectors).length - 1];
|
|
243
337
|
if (!lastSelector.evaldCondition) {
|
|
244
338
|
return false;
|
|
245
339
|
}
|
|
246
340
|
if (lastSelector.condition &&
|
|
247
|
-
!lastSelector.condition.eval(
|
|
341
|
+
!lastSelector.condition.eval(
|
|
342
|
+
new contexts.Eval(context,
|
|
343
|
+
context.frames))) {
|
|
248
344
|
return false;
|
|
249
345
|
}
|
|
250
346
|
return true;
|
|
251
|
-
}
|
|
252
|
-
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
resetCache() {
|
|
253
350
|
this._rulesets = null;
|
|
254
351
|
this._variables = null;
|
|
255
352
|
this._properties = null;
|
|
256
353
|
this._lookups = {};
|
|
257
|
-
}
|
|
258
|
-
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
variables() {
|
|
259
357
|
if (!this._variables) {
|
|
260
|
-
this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
|
|
261
|
-
if (r instanceof
|
|
262
|
-
hash[r.name] = r;
|
|
358
|
+
this._variables = !this.rules ? {} : this.rules.reduce(function (/** @type {Object<string, Declaration>} */ hash, /** @type {Node} */ r) {
|
|
359
|
+
if (r instanceof Declaration && r.variable === true) {
|
|
360
|
+
hash[/** @type {string} */ (r.name)] = r;
|
|
263
361
|
}
|
|
264
362
|
// when evaluating variables in an import statement, imports have not been eval'd
|
|
265
363
|
// so we need to go inside import statements.
|
|
266
364
|
// guard against root being a string (in the case of inlined less)
|
|
267
|
-
if (r.type === 'Import' && r.root && r.root.variables) {
|
|
268
|
-
|
|
269
|
-
for (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
hash[name_1] = r.root.variable(name_1);
|
|
365
|
+
if (r.type === 'Import' && /** @type {RuleNode} */ (r).root && /** @type {RuleNode & { root: Ruleset }} */ (r).root.variables) {
|
|
366
|
+
const vars = /** @type {RuleNode & { root: Ruleset }} */ (r).root.variables();
|
|
367
|
+
for (const name in vars) {
|
|
368
|
+
if (Object.prototype.hasOwnProperty.call(vars, name)) {
|
|
369
|
+
hash[name] = /** @type {Declaration} */ (/** @type {RuleNode & { root: Ruleset }} */ (r).root.variable(name));
|
|
273
370
|
}
|
|
274
371
|
}
|
|
275
372
|
}
|
|
@@ -277,65 +374,77 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
277
374
|
}, {});
|
|
278
375
|
}
|
|
279
376
|
return this._variables;
|
|
280
|
-
}
|
|
281
|
-
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
properties() {
|
|
282
380
|
if (!this._properties) {
|
|
283
|
-
this._properties = !this.rules ? {} : this.rules.reduce(function (hash, r) {
|
|
284
|
-
if (r instanceof
|
|
285
|
-
|
|
286
|
-
r.name[0].value : r.name;
|
|
381
|
+
this._properties = !this.rules ? {} : this.rules.reduce(function (/** @type {Object<string, Declaration[]>} */ hash, /** @type {Node} */ r) {
|
|
382
|
+
if (r instanceof Declaration && r.variable !== true) {
|
|
383
|
+
const name = (/** @type {Node[]} */ (r.name).length === 1) && (/** @type {Node[]} */ (r.name)[0] instanceof Keyword) ?
|
|
384
|
+
/** @type {string} */ (/** @type {Node[]} */ (r.name)[0].value) : /** @type {string} */ (r.name);
|
|
287
385
|
// Properties don't overwrite as they can merge
|
|
288
|
-
if (!hash[
|
|
289
|
-
hash[
|
|
386
|
+
if (!hash[`$${name}`]) {
|
|
387
|
+
hash[`$${name}`] = [ r ];
|
|
290
388
|
}
|
|
291
389
|
else {
|
|
292
|
-
hash[
|
|
390
|
+
hash[`$${name}`].push(r);
|
|
293
391
|
}
|
|
294
392
|
}
|
|
295
393
|
return hash;
|
|
296
394
|
}, {});
|
|
297
395
|
}
|
|
298
396
|
return this._properties;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/** @param {string} name */
|
|
400
|
+
variable(name) {
|
|
401
|
+
const decl = this.variables()[name];
|
|
302
402
|
if (decl) {
|
|
303
403
|
return this.parseValue(decl);
|
|
304
404
|
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/** @param {string} name */
|
|
408
|
+
property(name) {
|
|
409
|
+
const decl = this.properties()[name];
|
|
308
410
|
if (decl) {
|
|
309
411
|
return this.parseValue(decl);
|
|
310
412
|
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
lastDeclaration() {
|
|
416
|
+
for (let i = /** @type {Node[]} */ (this.rules).length; i > 0; i--) {
|
|
417
|
+
const decl = /** @type {Node[]} */ (this.rules)[i - 1];
|
|
418
|
+
if (decl instanceof Declaration) {
|
|
316
419
|
return this.parseValue(decl);
|
|
317
420
|
}
|
|
318
421
|
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** @param {Declaration | Declaration[]} toParse */
|
|
425
|
+
parseValue(toParse) {
|
|
426
|
+
const self = this;
|
|
427
|
+
/** @param {Declaration} decl */
|
|
322
428
|
function transformDeclaration(decl) {
|
|
323
|
-
if (decl.value instanceof
|
|
429
|
+
if (decl.value instanceof Anonymous && !/** @type {Declaration & { parsed?: boolean }} */ (decl).parsed) {
|
|
324
430
|
if (typeof decl.value.value === 'string') {
|
|
325
|
-
new
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
431
|
+
new (/** @type {new (...args: [EvalContext, object, FileInfo, number]) => { parseNode: Function }} */ (/** @type {unknown} */ (Parser)))(/** @type {{ context: EvalContext, importManager: object }} */ (/** @type {Ruleset} */ (this).parse).context, /** @type {{ context: EvalContext, importManager: object }} */ (/** @type {Ruleset} */ (this).parse).importManager, decl.fileInfo(), decl.value.getIndex()).parseNode(
|
|
432
|
+
decl.value.value,
|
|
433
|
+
['value', 'important'],
|
|
434
|
+
function(/** @type {Error | null} */ err, /** @type {Node[]} */ result) {
|
|
435
|
+
if (err) {
|
|
436
|
+
decl.parsed = /** @type {Node} */ (/** @type {unknown} */ (true));
|
|
437
|
+
}
|
|
438
|
+
if (result) {
|
|
439
|
+
decl.value = result[0];
|
|
440
|
+
/** @type {Declaration & { important?: string }} */ (decl).important = /** @type {string} */ (/** @type {unknown} */ (result[1])) || '';
|
|
441
|
+
decl.parsed = /** @type {Node} */ (/** @type {unknown} */ (true));
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
} else {
|
|
445
|
+
decl.parsed = /** @type {Node} */ (/** @type {unknown} */ (true));
|
|
338
446
|
}
|
|
447
|
+
|
|
339
448
|
return decl;
|
|
340
449
|
}
|
|
341
450
|
else {
|
|
@@ -346,63 +455,79 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
346
455
|
return transformDeclaration.call(self, toParse);
|
|
347
456
|
}
|
|
348
457
|
else {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
},
|
|
356
|
-
rulesets: function () {
|
|
357
|
-
if (!this.rules) {
|
|
358
|
-
return [];
|
|
458
|
+
/** @type {Declaration[]} */
|
|
459
|
+
const nodes = [];
|
|
460
|
+
for (let ti = 0; ti < toParse.length; ti++) {
|
|
461
|
+
nodes.push(transformDeclaration.call(self, toParse[ti]));
|
|
462
|
+
}
|
|
463
|
+
return nodes;
|
|
359
464
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
rulesets() {
|
|
468
|
+
if (!this.rules) { return []; }
|
|
469
|
+
|
|
470
|
+
/** @type {Node[]} */
|
|
471
|
+
const filtRules = [];
|
|
472
|
+
const rules = this.rules;
|
|
473
|
+
/** @type {number} */
|
|
474
|
+
let i;
|
|
475
|
+
/** @type {Node} */
|
|
476
|
+
let rule;
|
|
477
|
+
|
|
364
478
|
for (i = 0; (rule = rules[i]); i++) {
|
|
365
|
-
if (rule.isRuleset) {
|
|
479
|
+
if (/** @type {RuleNode} */ (rule).isRuleset) {
|
|
366
480
|
filtRules.push(rule);
|
|
367
481
|
}
|
|
368
482
|
}
|
|
483
|
+
|
|
369
484
|
return filtRules;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/** @param {Node} rule */
|
|
488
|
+
prependRule(rule) {
|
|
489
|
+
const rules = this.rules;
|
|
373
490
|
if (rules) {
|
|
374
491
|
rules.unshift(rule);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
this.rules = [rule];
|
|
492
|
+
} else {
|
|
493
|
+
this.rules = [ rule ];
|
|
378
494
|
}
|
|
379
495
|
this.setParent(rule, this);
|
|
380
|
-
}
|
|
381
|
-
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* @param {Selector} selector
|
|
500
|
+
* @param {Ruleset | null} [self]
|
|
501
|
+
* @param {((rule: Node) => boolean)} [filter]
|
|
502
|
+
* @returns {{ rule: Node, path: Node[] }[]}
|
|
503
|
+
*/
|
|
504
|
+
find(selector, self, filter) {
|
|
382
505
|
self = self || this;
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
506
|
+
/** @type {{ rule: Node, path: Node[] }[]} */
|
|
507
|
+
const rules = [];
|
|
508
|
+
/** @type {number | undefined} */
|
|
509
|
+
let match;
|
|
510
|
+
/** @type {{ rule: Node, path: Node[] }[]} */
|
|
511
|
+
let foundMixins;
|
|
512
|
+
const key = selector.toCSS(/** @type {EvalContext} */ ({}));
|
|
513
|
+
|
|
514
|
+
if (key in this._lookups) { return /** @type {{ rule: Node, path: Node[] }[]} */ (this._lookups[key]); }
|
|
515
|
+
|
|
390
516
|
this.rulesets().forEach(function (rule) {
|
|
391
517
|
if (rule !== self) {
|
|
392
|
-
for (
|
|
393
|
-
match = selector.match(rule.selectors[j]);
|
|
518
|
+
for (let j = 0; j < /** @type {RuleNode} */ (rule).selectors.length; j++) {
|
|
519
|
+
match = selector.match(/** @type {RuleNode} */ (rule).selectors[j]);
|
|
394
520
|
if (match) {
|
|
395
521
|
if (selector.elements.length > match) {
|
|
396
522
|
if (!filter || filter(rule)) {
|
|
397
|
-
foundMixins = rule.find(new
|
|
398
|
-
for (
|
|
523
|
+
foundMixins = /** @type {Ruleset} */ (/** @type {unknown} */ (rule)).find(new Selector(selector.elements.slice(match)), self, filter);
|
|
524
|
+
for (let i = 0; i < foundMixins.length; ++i) {
|
|
399
525
|
foundMixins[i].path.push(rule);
|
|
400
526
|
}
|
|
401
527
|
Array.prototype.push.apply(rules, foundMixins);
|
|
402
528
|
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
rules.push({ rule: rule, path: [] });
|
|
529
|
+
} else {
|
|
530
|
+
rules.push({ rule, path: []});
|
|
406
531
|
}
|
|
407
532
|
break;
|
|
408
533
|
}
|
|
@@ -411,139 +536,211 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
411
536
|
});
|
|
412
537
|
this._lookups[key] = rules;
|
|
413
538
|
return rules;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* @param {EvalContext} context
|
|
543
|
+
* @param {CSSOutput} output
|
|
544
|
+
*/
|
|
545
|
+
genCSS(context, output) {
|
|
546
|
+
/** @type {number} */
|
|
547
|
+
let i;
|
|
548
|
+
/** @type {number} */
|
|
549
|
+
let j;
|
|
550
|
+
/** @type {Node[]} */
|
|
551
|
+
const charsetRuleNodes = [];
|
|
552
|
+
/** @type {Node[]} */
|
|
553
|
+
let ruleNodes = [];
|
|
554
|
+
|
|
555
|
+
let // Line number debugging
|
|
556
|
+
debugInfo;
|
|
557
|
+
|
|
558
|
+
/** @type {Node} */
|
|
559
|
+
let rule;
|
|
560
|
+
/** @type {Selector[]} */
|
|
561
|
+
let path;
|
|
562
|
+
|
|
424
563
|
context.tabLevel = (context.tabLevel || 0);
|
|
564
|
+
|
|
425
565
|
if (!this.root) {
|
|
426
566
|
context.tabLevel++;
|
|
427
567
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
568
|
+
|
|
569
|
+
const tabRuleStr = context.compress ? '' : Array(context.tabLevel + 1).join(' ');
|
|
570
|
+
const tabSetStr = context.compress ? '' : Array(context.tabLevel).join(' ');
|
|
571
|
+
/** @type {string} */
|
|
572
|
+
let sep;
|
|
573
|
+
|
|
574
|
+
let charsetNodeIndex = 0;
|
|
575
|
+
let importNodeIndex = 0;
|
|
576
|
+
for (i = 0; (rule = /** @type {Node[]} */ (this.rules)[i]); i++) {
|
|
577
|
+
if (rule instanceof Comment) {
|
|
435
578
|
if (importNodeIndex === i) {
|
|
436
579
|
importNodeIndex++;
|
|
437
580
|
}
|
|
438
581
|
ruleNodes.push(rule);
|
|
439
|
-
}
|
|
440
|
-
else if (rule.isCharset && rule.isCharset()) {
|
|
582
|
+
} else if (/** @type {RuleNode} */ (rule).isCharset && /** @type {RuleNode} */ (rule).isCharset()) {
|
|
441
583
|
ruleNodes.splice(charsetNodeIndex, 0, rule);
|
|
442
584
|
charsetNodeIndex++;
|
|
443
585
|
importNodeIndex++;
|
|
444
|
-
}
|
|
445
|
-
else if (rule.type === 'Import') {
|
|
586
|
+
} else if (rule.type === 'Import') {
|
|
446
587
|
ruleNodes.splice(importNodeIndex, 0, rule);
|
|
447
588
|
importNodeIndex++;
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
589
|
+
} else {
|
|
450
590
|
ruleNodes.push(rule);
|
|
451
591
|
}
|
|
452
592
|
}
|
|
453
593
|
ruleNodes = charsetRuleNodes.concat(ruleNodes);
|
|
594
|
+
|
|
454
595
|
// If this is the root node, we don't render
|
|
455
596
|
// a selector, or {}.
|
|
456
597
|
if (!this.root) {
|
|
457
|
-
debugInfo = (
|
|
598
|
+
debugInfo = getDebugInfo(context, /** @type {{ debugInfo: { lineNumber: number, fileName: string } }} */ (/** @type {unknown} */ (this)), tabSetStr);
|
|
599
|
+
|
|
458
600
|
if (debugInfo) {
|
|
459
601
|
output.add(debugInfo);
|
|
460
602
|
output.add(tabSetStr);
|
|
461
603
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
604
|
+
|
|
605
|
+
const paths = /** @type {Selector[][]} */ (this.paths);
|
|
606
|
+
const pathCnt = paths.length;
|
|
607
|
+
/** @type {number} */
|
|
608
|
+
let pathSubCnt;
|
|
609
|
+
|
|
610
|
+
sep = context.compress ? ',' : (`,\n${tabSetStr}`);
|
|
611
|
+
|
|
466
612
|
for (i = 0; i < pathCnt; i++) {
|
|
467
613
|
path = paths[i];
|
|
468
|
-
if (!(pathSubCnt = path.length)) {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
output.add(sep);
|
|
473
|
-
}
|
|
474
|
-
context.firstSelector = true;
|
|
614
|
+
if (!(pathSubCnt = path.length)) { continue; }
|
|
615
|
+
if (i > 0) { output.add(sep); }
|
|
616
|
+
|
|
617
|
+
/** @type {EvalContext & { firstSelector?: boolean }} */ (context).firstSelector = true;
|
|
475
618
|
path[0].genCSS(context, output);
|
|
476
|
-
|
|
619
|
+
|
|
620
|
+
/** @type {EvalContext & { firstSelector?: boolean }} */ (context).firstSelector = false;
|
|
477
621
|
for (j = 1; j < pathSubCnt; j++) {
|
|
478
622
|
path[j].genCSS(context, output);
|
|
479
623
|
}
|
|
480
624
|
}
|
|
625
|
+
|
|
481
626
|
output.add((context.compress ? '{' : ' {\n') + tabRuleStr);
|
|
482
627
|
}
|
|
628
|
+
|
|
483
629
|
// Compile rules and rulesets
|
|
484
630
|
for (i = 0; (rule = ruleNodes[i]); i++) {
|
|
631
|
+
|
|
485
632
|
if (i + 1 === ruleNodes.length) {
|
|
486
633
|
context.lastRule = true;
|
|
487
634
|
}
|
|
488
|
-
|
|
489
|
-
|
|
635
|
+
|
|
636
|
+
const currentLastRule = context.lastRule;
|
|
637
|
+
if (rule.isRulesetLike()) {
|
|
490
638
|
context.lastRule = false;
|
|
491
639
|
}
|
|
640
|
+
|
|
492
641
|
if (rule.genCSS) {
|
|
493
642
|
rule.genCSS(context, output);
|
|
643
|
+
} else if (rule.value) {
|
|
644
|
+
output.add(/** @type {string} */ (rule.value).toString());
|
|
494
645
|
}
|
|
495
|
-
|
|
496
|
-
output.add(rule.value.toString());
|
|
497
|
-
}
|
|
646
|
+
|
|
498
647
|
context.lastRule = currentLastRule;
|
|
648
|
+
|
|
499
649
|
if (!context.lastRule && rule.isVisible()) {
|
|
500
|
-
output.add(context.compress ? '' : (
|
|
501
|
-
}
|
|
502
|
-
else {
|
|
650
|
+
output.add(context.compress ? '' : (`\n${tabRuleStr}`));
|
|
651
|
+
} else {
|
|
503
652
|
context.lastRule = false;
|
|
504
653
|
}
|
|
505
654
|
}
|
|
655
|
+
|
|
506
656
|
if (!this.root) {
|
|
507
|
-
output.add((context.compress ? '}' :
|
|
657
|
+
output.add((context.compress ? '}' : `\n${tabSetStr}}`));
|
|
508
658
|
context.tabLevel--;
|
|
509
659
|
}
|
|
660
|
+
|
|
510
661
|
if (!output.isEmpty() && !context.compress && this.firstRoot) {
|
|
511
662
|
output.add('\n');
|
|
512
663
|
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* @param {Selector[][]} paths
|
|
668
|
+
* @param {Selector[][]} context
|
|
669
|
+
* @param {Selector[]} selectors
|
|
670
|
+
*/
|
|
671
|
+
joinSelectors(paths, context, selectors) {
|
|
672
|
+
for (let s = 0; s < selectors.length; s++) {
|
|
516
673
|
this.joinSelector(paths, context, selectors[s]);
|
|
517
674
|
}
|
|
518
|
-
}
|
|
519
|
-
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* @param {Selector[][]} paths
|
|
679
|
+
* @param {Selector[][]} context
|
|
680
|
+
* @param {Selector} selector
|
|
681
|
+
*/
|
|
682
|
+
joinSelector(paths, context, selector) {
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* @param {Selector[]} elementsToPak
|
|
686
|
+
* @param {Element} originalElement
|
|
687
|
+
* @returns {Paren}
|
|
688
|
+
*/
|
|
520
689
|
function createParenthesis(elementsToPak, originalElement) {
|
|
521
|
-
|
|
690
|
+
/** @type {Paren} */
|
|
691
|
+
let replacementParen;
|
|
692
|
+
/** @type {number} */
|
|
693
|
+
let j;
|
|
522
694
|
if (elementsToPak.length === 0) {
|
|
523
|
-
replacementParen = new
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
var insideParent = new Array(elementsToPak.length);
|
|
695
|
+
replacementParen = new Paren(elementsToPak[0]);
|
|
696
|
+
} else {
|
|
697
|
+
const insideParent = new Array(elementsToPak.length);
|
|
527
698
|
for (j = 0; j < elementsToPak.length; j++) {
|
|
528
|
-
insideParent[j] = new
|
|
699
|
+
insideParent[j] = new Element(
|
|
700
|
+
null,
|
|
701
|
+
elementsToPak[j],
|
|
702
|
+
originalElement.isVariable,
|
|
703
|
+
originalElement._index,
|
|
704
|
+
originalElement._fileInfo
|
|
705
|
+
);
|
|
529
706
|
}
|
|
530
|
-
replacementParen = new
|
|
707
|
+
replacementParen = new Paren(new Selector(insideParent));
|
|
531
708
|
}
|
|
532
709
|
return replacementParen;
|
|
533
710
|
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* @param {Paren | Selector} containedElement
|
|
714
|
+
* @param {Element} originalElement
|
|
715
|
+
* @returns {Selector}
|
|
716
|
+
*/
|
|
534
717
|
function createSelector(containedElement, originalElement) {
|
|
535
|
-
|
|
536
|
-
element
|
|
537
|
-
|
|
718
|
+
/** @type {Element} */
|
|
719
|
+
let element;
|
|
720
|
+
/** @type {Selector} */
|
|
721
|
+
let selector;
|
|
722
|
+
element = new Element(null, containedElement, originalElement.isVariable, originalElement._index, originalElement._fileInfo);
|
|
723
|
+
selector = new Selector([element]);
|
|
538
724
|
return selector;
|
|
539
725
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* @param {Selector[]} beginningPath
|
|
729
|
+
* @param {Selector[]} addPath
|
|
730
|
+
* @param {Element} replacedElement
|
|
731
|
+
* @param {Selector} originalSelector
|
|
732
|
+
* @returns {Selector[]}
|
|
733
|
+
*/
|
|
543
734
|
function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
|
|
544
|
-
|
|
735
|
+
/** @type {Selector[]} */
|
|
736
|
+
let newSelectorPath;
|
|
737
|
+
/** @type {Selector} */
|
|
738
|
+
let lastSelector;
|
|
739
|
+
/** @type {Selector} */
|
|
740
|
+
let newJoinedSelector;
|
|
545
741
|
// our new selector path
|
|
546
742
|
newSelectorPath = [];
|
|
743
|
+
|
|
547
744
|
// construct the joined selector - if & is the first thing this will be empty,
|
|
548
745
|
// if not newJoinedSelector will be the last set of elements in the selector
|
|
549
746
|
if (beginningPath.length > 0) {
|
|
@@ -554,68 +751,99 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
554
751
|
else {
|
|
555
752
|
newJoinedSelector = originalSelector.createDerived([]);
|
|
556
753
|
}
|
|
754
|
+
|
|
557
755
|
if (addPath.length > 0) {
|
|
558
756
|
// /deep/ is a CSS4 selector - (removed, so should deprecate)
|
|
559
757
|
// that is valid without anything in front of it
|
|
560
758
|
// so if the & does not have a combinator that is "" or " " then
|
|
561
759
|
// and there is a combinator on the parent, then grab that.
|
|
562
760
|
// this also allows + a { & .b { .a & { ... though not sure why you would want to do that
|
|
563
|
-
|
|
564
|
-
|
|
761
|
+
let combinator = replacedElement.combinator;
|
|
762
|
+
|
|
763
|
+
const parentEl = addPath[0].elements[0];
|
|
565
764
|
if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
|
|
566
765
|
combinator = parentEl.combinator;
|
|
567
766
|
}
|
|
568
767
|
// join the elements so far with the first part of the parent
|
|
569
|
-
newJoinedSelector.elements.push(new
|
|
768
|
+
newJoinedSelector.elements.push(new Element(
|
|
769
|
+
combinator,
|
|
770
|
+
parentEl.value,
|
|
771
|
+
replacedElement.isVariable,
|
|
772
|
+
replacedElement._index,
|
|
773
|
+
replacedElement._fileInfo
|
|
774
|
+
));
|
|
570
775
|
newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
|
|
571
776
|
}
|
|
777
|
+
|
|
572
778
|
// now add the joined selector - but only if it is not empty
|
|
573
779
|
if (newJoinedSelector.elements.length !== 0) {
|
|
574
780
|
newSelectorPath.push(newJoinedSelector);
|
|
575
781
|
}
|
|
782
|
+
|
|
576
783
|
// put together the parent selectors after the join (e.g. the rest of the parent)
|
|
577
784
|
if (addPath.length > 1) {
|
|
578
|
-
|
|
579
|
-
restOfPath = restOfPath.map(function (selector) {
|
|
785
|
+
let restOfPath = addPath.slice(1);
|
|
786
|
+
restOfPath = restOfPath.map(function (/** @type {Selector} */ selector) {
|
|
580
787
|
return selector.createDerived(selector.elements, []);
|
|
581
788
|
});
|
|
582
789
|
newSelectorPath = newSelectorPath.concat(restOfPath);
|
|
583
790
|
}
|
|
584
791
|
return newSelectorPath;
|
|
585
792
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* @param {Selector[][]} beginningPath
|
|
796
|
+
* @param {Selector[]} addPaths
|
|
797
|
+
* @param {Element} replacedElement
|
|
798
|
+
* @param {Selector} originalSelector
|
|
799
|
+
* @param {Selector[][]} result
|
|
800
|
+
* @returns {Selector[][]}
|
|
801
|
+
*/
|
|
802
|
+
function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
|
|
803
|
+
/** @type {number} */
|
|
804
|
+
let j;
|
|
591
805
|
for (j = 0; j < beginningPath.length; j++) {
|
|
592
|
-
|
|
806
|
+
const newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
|
|
593
807
|
result.push(newSelectorPath);
|
|
594
808
|
}
|
|
595
809
|
return result;
|
|
596
810
|
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* @param {Element[]} elements
|
|
814
|
+
* @param {Selector[][]} selectors
|
|
815
|
+
*/
|
|
597
816
|
function mergeElementsOnToSelectors(elements, selectors) {
|
|
598
|
-
|
|
817
|
+
/** @type {number} */
|
|
818
|
+
let i;
|
|
819
|
+
/** @type {Selector[]} */
|
|
820
|
+
let sel;
|
|
821
|
+
|
|
599
822
|
if (elements.length === 0) {
|
|
600
|
-
return;
|
|
823
|
+
return ;
|
|
601
824
|
}
|
|
602
825
|
if (selectors.length === 0) {
|
|
603
|
-
selectors.push([new
|
|
826
|
+
selectors.push([ new Selector(elements) ]);
|
|
604
827
|
return;
|
|
605
828
|
}
|
|
829
|
+
|
|
606
830
|
for (i = 0; (sel = selectors[i]); i++) {
|
|
607
831
|
// if the previous thing in sel is a parent this needs to join on to it
|
|
608
832
|
if (sel.length > 0) {
|
|
609
833
|
sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
|
|
610
834
|
}
|
|
611
835
|
else {
|
|
612
|
-
sel.push(new
|
|
836
|
+
sel.push(new Selector(elements));
|
|
613
837
|
}
|
|
614
838
|
}
|
|
615
839
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* @param {Selector[][]} paths
|
|
843
|
+
* @param {Selector[][]} context
|
|
844
|
+
* @param {Selector} inSelector
|
|
845
|
+
* @returns {boolean}
|
|
846
|
+
*/
|
|
619
847
|
function replaceParentSelector(paths, context, inSelector) {
|
|
620
848
|
// The paths are [[Selector]]
|
|
621
849
|
// The first list is a list of comma separated selectors
|
|
@@ -627,18 +855,47 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
627
855
|
// }
|
|
628
856
|
// == [[.a] [.c]] [[.b] [.c]]
|
|
629
857
|
//
|
|
630
|
-
|
|
858
|
+
/** @type {number} */
|
|
859
|
+
let i;
|
|
860
|
+
/** @type {number} */
|
|
861
|
+
let j;
|
|
862
|
+
/** @type {number} */
|
|
863
|
+
let k;
|
|
864
|
+
/** @type {Element[]} */
|
|
865
|
+
let currentElements;
|
|
866
|
+
/** @type {Selector[][]} */
|
|
867
|
+
let newSelectors;
|
|
868
|
+
/** @type {Selector[][]} */
|
|
869
|
+
let selectorsMultiplied;
|
|
870
|
+
/** @type {Selector[]} */
|
|
871
|
+
let sel;
|
|
872
|
+
/** @type {Element} */
|
|
873
|
+
let el;
|
|
874
|
+
let hadParentSelector = false;
|
|
875
|
+
/** @type {number} */
|
|
876
|
+
let length;
|
|
877
|
+
/** @type {Selector} */
|
|
878
|
+
let lastSelector;
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* @param {Element} element
|
|
882
|
+
* @returns {Selector | null}
|
|
883
|
+
*/
|
|
631
884
|
function findNestedSelector(element) {
|
|
632
|
-
|
|
633
|
-
|
|
885
|
+
/** @type {Node} */
|
|
886
|
+
let maybeSelector;
|
|
887
|
+
if (!(element.value instanceof Paren)) {
|
|
634
888
|
return null;
|
|
635
889
|
}
|
|
636
|
-
|
|
637
|
-
|
|
890
|
+
|
|
891
|
+
maybeSelector = /** @type {Node} */ (element.value.value);
|
|
892
|
+
if (!(maybeSelector instanceof Selector)) {
|
|
638
893
|
return null;
|
|
639
894
|
}
|
|
895
|
+
|
|
640
896
|
return maybeSelector;
|
|
641
897
|
}
|
|
898
|
+
|
|
642
899
|
// the elements from the current selector so far
|
|
643
900
|
currentElements = [];
|
|
644
901
|
// the current list of new selectors to add to the path.
|
|
@@ -647,38 +904,74 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
647
904
|
newSelectors = [
|
|
648
905
|
[]
|
|
649
906
|
];
|
|
907
|
+
|
|
650
908
|
for (i = 0; (el = inSelector.elements[i]); i++) {
|
|
651
909
|
// non parent reference elements just get added
|
|
652
910
|
if (el.value !== '&') {
|
|
653
|
-
|
|
911
|
+
const nestedSelector = findNestedSelector(el);
|
|
654
912
|
if (nestedSelector !== null) {
|
|
655
913
|
// merge the current list of non parent selector elements
|
|
656
914
|
// on to the current list of selectors to add
|
|
657
915
|
mergeElementsOnToSelectors(currentElements, newSelectors);
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
916
|
+
|
|
917
|
+
/** @type {Selector[][]} */
|
|
918
|
+
const nestedPaths = [];
|
|
919
|
+
/** @type {boolean | undefined} */
|
|
920
|
+
let replaced;
|
|
921
|
+
/** @type {Selector[][]} */
|
|
922
|
+
const replacedNewSelectors = [];
|
|
923
|
+
|
|
924
|
+
// Check if this is a comma-separated selector list inside the paren
|
|
925
|
+
// e.g. :not(&.a, &.b) produces Selector([Selector, Anonymous(','), Selector])
|
|
926
|
+
const hasSubSelectors = nestedSelector.elements.some(e => e instanceof Selector);
|
|
927
|
+
|
|
928
|
+
if (hasSubSelectors) {
|
|
929
|
+
// Process each sub-selector individually
|
|
930
|
+
/** @type {(Element | Selector)[]} */
|
|
931
|
+
const resolvedElements = [];
|
|
932
|
+
for (const subEl of nestedSelector.elements) {
|
|
933
|
+
if (subEl instanceof Selector) {
|
|
934
|
+
/** @type {Selector[][]} */
|
|
935
|
+
const subPaths = [];
|
|
936
|
+
const subReplaced = replaceParentSelector(subPaths, context, subEl);
|
|
937
|
+
replaced = replaced || subReplaced;
|
|
938
|
+
if (subPaths.length > 0 && subPaths[0].length > 0) {
|
|
939
|
+
resolvedElements.push(subPaths[0][0]);
|
|
940
|
+
} else {
|
|
941
|
+
resolvedElements.push(subEl);
|
|
942
|
+
}
|
|
943
|
+
} else {
|
|
944
|
+
resolvedElements.push(subEl);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
hadParentSelector = hadParentSelector || /** @type {boolean} */ (replaced);
|
|
948
|
+
const resolvedNestedSelector = new Selector(resolvedElements);
|
|
949
|
+
const replacementSelector = createSelector(createParenthesis([resolvedNestedSelector], el), el);
|
|
666
950
|
addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
|
|
951
|
+
} else {
|
|
952
|
+
replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
|
|
953
|
+
hadParentSelector = hadParentSelector || replaced;
|
|
954
|
+
// the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
|
|
955
|
+
for (k = 0; k < nestedPaths.length; k++) {
|
|
956
|
+
const replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
|
|
957
|
+
addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
|
|
958
|
+
}
|
|
667
959
|
}
|
|
668
960
|
newSelectors = replacedNewSelectors;
|
|
669
961
|
currentElements = [];
|
|
670
|
-
}
|
|
671
|
-
else {
|
|
962
|
+
} else {
|
|
672
963
|
currentElements.push(el);
|
|
673
964
|
}
|
|
674
|
-
|
|
675
|
-
else {
|
|
965
|
+
|
|
966
|
+
} else {
|
|
676
967
|
hadParentSelector = true;
|
|
677
968
|
// the new list of selectors to add
|
|
678
969
|
selectorsMultiplied = [];
|
|
970
|
+
|
|
679
971
|
// merge the current list of non parent selector elements
|
|
680
972
|
// on to the current list of selectors to add
|
|
681
973
|
mergeElementsOnToSelectors(currentElements, newSelectors);
|
|
974
|
+
|
|
682
975
|
// loop through our current selectors
|
|
683
976
|
for (j = 0; j < newSelectors.length; j++) {
|
|
684
977
|
sel = newSelectors[j];
|
|
@@ -688,7 +981,7 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
688
981
|
// the combinator used on el should now be applied to the next element instead so that
|
|
689
982
|
// it is not lost
|
|
690
983
|
if (sel.length > 0) {
|
|
691
|
-
sel[0].elements.push(new
|
|
984
|
+
sel[0].elements.push(new Element(el.combinator, '', el.isVariable, el._index, el._fileInfo));
|
|
692
985
|
}
|
|
693
986
|
selectorsMultiplied.push(sel);
|
|
694
987
|
}
|
|
@@ -697,20 +990,23 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
697
990
|
for (k = 0; k < context.length; k++) {
|
|
698
991
|
// We need to put the current selectors
|
|
699
992
|
// then join the last selector's elements on to the parents selectors
|
|
700
|
-
|
|
993
|
+
const newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
|
|
701
994
|
// add that to our new set of selectors
|
|
702
995
|
selectorsMultiplied.push(newSelectorPath);
|
|
703
996
|
}
|
|
704
997
|
}
|
|
705
998
|
}
|
|
999
|
+
|
|
706
1000
|
// our new selectors has been multiplied, so reset the state
|
|
707
1001
|
newSelectors = selectorsMultiplied;
|
|
708
1002
|
currentElements = [];
|
|
709
1003
|
}
|
|
710
1004
|
}
|
|
1005
|
+
|
|
711
1006
|
// if we have any elements left over (e.g. .a& .b == .b)
|
|
712
1007
|
// add them on to all the current selectors
|
|
713
1008
|
mergeElementsOnToSelectors(currentElements, newSelectors);
|
|
1009
|
+
|
|
714
1010
|
for (i = 0; i < newSelectors.length; i++) {
|
|
715
1011
|
length = newSelectors[i].length;
|
|
716
1012
|
if (length > 0) {
|
|
@@ -719,22 +1015,38 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
719
1015
|
newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
|
|
720
1016
|
}
|
|
721
1017
|
}
|
|
1018
|
+
|
|
722
1019
|
return hadParentSelector;
|
|
723
1020
|
}
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
* @param {VisibilityInfo} visibilityInfo
|
|
1024
|
+
* @param {Selector} deriveFrom
|
|
1025
|
+
*/
|
|
724
1026
|
function deriveSelector(visibilityInfo, deriveFrom) {
|
|
725
|
-
|
|
1027
|
+
const newSelector = deriveFrom.createDerived(deriveFrom.elements, deriveFrom.extendList, deriveFrom.evaldCondition);
|
|
726
1028
|
newSelector.copyVisibilityInfo(visibilityInfo);
|
|
727
1029
|
return newSelector;
|
|
728
1030
|
}
|
|
1031
|
+
|
|
729
1032
|
// joinSelector code follows
|
|
730
|
-
|
|
1033
|
+
/** @type {number} */
|
|
1034
|
+
let i;
|
|
1035
|
+
/** @type {Selector[][]} */
|
|
1036
|
+
let newPaths;
|
|
1037
|
+
/** @type {boolean} */
|
|
1038
|
+
let hadParentSelector;
|
|
1039
|
+
|
|
731
1040
|
newPaths = [];
|
|
732
1041
|
hadParentSelector = replaceParentSelector(newPaths, context, selector);
|
|
1042
|
+
|
|
733
1043
|
if (!hadParentSelector) {
|
|
734
1044
|
if (context.length > 0) {
|
|
735
1045
|
newPaths = [];
|
|
736
1046
|
for (i = 0; i < context.length; i++) {
|
|
737
|
-
|
|
1047
|
+
|
|
1048
|
+
const concatenated = context[i].map(deriveSelector.bind(this, selector.visibilityInfo()));
|
|
1049
|
+
|
|
738
1050
|
concatenated.push(selector);
|
|
739
1051
|
newPaths.push(concatenated);
|
|
740
1052
|
}
|
|
@@ -743,10 +1055,12 @@ Ruleset.prototype = Object.assign(new node_1.default(), {
|
|
|
743
1055
|
newPaths = [[selector]];
|
|
744
1056
|
}
|
|
745
1057
|
}
|
|
1058
|
+
|
|
746
1059
|
for (i = 0; i < newPaths.length; i++) {
|
|
747
1060
|
paths.push(newPaths[i]);
|
|
748
1061
|
}
|
|
1062
|
+
|
|
749
1063
|
}
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
export default Ruleset;
|