less 4.9.0 → 5.0.0-alpha.2

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.
Files changed (131) hide show
  1. package/README.md +19 -5
  2. package/bin/lessc +190 -630
  3. package/dist/less-node.cjs +399 -14570
  4. package/index.cjs +5 -2
  5. package/lib/index.js +164 -0
  6. package/lib/lessc-helper.js +52 -0
  7. package/lib/logger.js +76 -0
  8. package/lib/options.d.ts +46 -0
  9. package/lib/options.js +145 -0
  10. package/lib/types.js +20 -0
  11. package/lib/version.js +19 -0
  12. package/package.json +32 -39
  13. package/dist/less.cjs +0 -15215
  14. package/dist/less.js +0 -15215
  15. package/dist/less.min.js +0 -11
  16. package/dist/less.min.js.map +0 -1
  17. package/lib/less/constants.js +0 -13
  18. package/lib/less/contexts.js +0 -165
  19. package/lib/less/data/colors.js +0 -150
  20. package/lib/less/data/index.js +0 -4
  21. package/lib/less/data/unit-conversions.js +0 -21
  22. package/lib/less/default-options.js +0 -89
  23. package/lib/less/deprecation.js +0 -82
  24. package/lib/less/environment/abstract-file-manager.js +0 -140
  25. package/lib/less/environment/abstract-plugin-loader.js +0 -185
  26. package/lib/less/environment/environment-api.ts +0 -21
  27. package/lib/less/environment/environment.js +0 -59
  28. package/lib/less/environment/file-manager-api.ts +0 -77
  29. package/lib/less/functions/boolean.js +0 -29
  30. package/lib/less/functions/color-blending.js +0 -85
  31. package/lib/less/functions/color.js +0 -452
  32. package/lib/less/functions/data-uri.js +0 -74
  33. package/lib/less/functions/default.js +0 -26
  34. package/lib/less/functions/function-caller.js +0 -55
  35. package/lib/less/functions/function-registry.js +0 -36
  36. package/lib/less/functions/index.js +0 -35
  37. package/lib/less/functions/list.js +0 -158
  38. package/lib/less/functions/math-helper.js +0 -22
  39. package/lib/less/functions/math.js +0 -30
  40. package/lib/less/functions/number.js +0 -95
  41. package/lib/less/functions/string.js +0 -39
  42. package/lib/less/functions/style.js +0 -29
  43. package/lib/less/functions/svg.js +0 -87
  44. package/lib/less/functions/types.js +0 -70
  45. package/lib/less/import-manager.js +0 -183
  46. package/lib/less/index.js +0 -95
  47. package/lib/less/less-error.js +0 -166
  48. package/lib/less/logger.js +0 -34
  49. package/lib/less/parse-tree.js +0 -124
  50. package/lib/less/parse.js +0 -87
  51. package/lib/less/parser/lookup-pattern.js +0 -26
  52. package/lib/less/parser/parser-input.js +0 -400
  53. package/lib/less/parser/parser.js +0 -2998
  54. package/lib/less/plugin-manager.js +0 -168
  55. package/lib/less/render.js +0 -41
  56. package/lib/less/source-map-builder.js +0 -82
  57. package/lib/less/source-map-output.js +0 -151
  58. package/lib/less/transform-tree.js +0 -102
  59. package/lib/less/tree/anonymous.js +0 -61
  60. package/lib/less/tree/assignment.js +0 -48
  61. package/lib/less/tree/atrule-syntax.js +0 -8
  62. package/lib/less/tree/atrule.js +0 -340
  63. package/lib/less/tree/attribute.js +0 -63
  64. package/lib/less/tree/call.js +0 -132
  65. package/lib/less/tree/color.js +0 -285
  66. package/lib/less/tree/combinator.js +0 -38
  67. package/lib/less/tree/comment.js +0 -48
  68. package/lib/less/tree/condition.js +0 -65
  69. package/lib/less/tree/container.js +0 -104
  70. package/lib/less/tree/debug-info.js +0 -80
  71. package/lib/less/tree/declaration.js +0 -139
  72. package/lib/less/tree/detached-ruleset.js +0 -45
  73. package/lib/less/tree/dimension.js +0 -215
  74. package/lib/less/tree/element.js +0 -93
  75. package/lib/less/tree/expression.js +0 -100
  76. package/lib/less/tree/extend.js +0 -88
  77. package/lib/less/tree/import.js +0 -299
  78. package/lib/less/tree/index.js +0 -56
  79. package/lib/less/tree/interpolated-variable.js +0 -106
  80. package/lib/less/tree/javascript.js +0 -45
  81. package/lib/less/tree/js-eval-node.js +0 -80
  82. package/lib/less/tree/keyword.js +0 -28
  83. package/lib/less/tree/media.js +0 -90
  84. package/lib/less/tree/merge-rules.js +0 -47
  85. package/lib/less/tree/mixin-call.js +0 -283
  86. package/lib/less/tree/mixin-definition.js +0 -319
  87. package/lib/less/tree/namespace-value.js +0 -95
  88. package/lib/less/tree/negative.js +0 -37
  89. package/lib/less/tree/nested-at-rule.js +0 -239
  90. package/lib/less/tree/node.js +0 -310
  91. package/lib/less/tree/operation.js +0 -81
  92. package/lib/less/tree/paren.js +0 -41
  93. package/lib/less/tree/property.js +0 -96
  94. package/lib/less/tree/query-in-parens.js +0 -64
  95. package/lib/less/tree/quoted.js +0 -131
  96. package/lib/less/tree/ruleset.js +0 -1068
  97. package/lib/less/tree/selector.js +0 -201
  98. package/lib/less/tree/unicode-descriptor.js +0 -14
  99. package/lib/less/tree/unit.js +0 -170
  100. package/lib/less/tree/url.js +0 -83
  101. package/lib/less/tree/value.js +0 -60
  102. package/lib/less/tree/variable-call.js +0 -60
  103. package/lib/less/tree/variable.js +0 -85
  104. package/lib/less/utils.js +0 -126
  105. package/lib/less/visitors/extend-visitor.js +0 -505
  106. package/lib/less/visitors/import-sequencer.js +0 -56
  107. package/lib/less/visitors/import-visitor.js +0 -203
  108. package/lib/less/visitors/index.js +0 -15
  109. package/lib/less/visitors/join-selector-visitor.js +0 -65
  110. package/lib/less/visitors/set-tree-visibility-visitor.js +0 -57
  111. package/lib/less/visitors/to-css-visitor.js +0 -332
  112. package/lib/less/visitors/visitor.js +0 -165
  113. package/lib/less-browser/add-default-options.js +0 -53
  114. package/lib/less-browser/bootstrap.js +0 -67
  115. package/lib/less-browser/browser.js +0 -65
  116. package/lib/less-browser/cache.js +0 -43
  117. package/lib/less-browser/error-reporting.js +0 -170
  118. package/lib/less-browser/file-manager.js +0 -112
  119. package/lib/less-browser/image-size.js +0 -28
  120. package/lib/less-browser/index.js +0 -284
  121. package/lib/less-browser/log-listener.js +0 -42
  122. package/lib/less-browser/plugin-loader.js +0 -24
  123. package/lib/less-browser/utils.js +0 -30
  124. package/lib/less-node/environment.js +0 -43
  125. package/lib/less-node/file-manager.js +0 -156
  126. package/lib/less-node/fs.js +0 -14
  127. package/lib/less-node/image-size.js +0 -78
  128. package/lib/less-node/index.js +0 -31
  129. package/lib/less-node/lessc-helper.js +0 -95
  130. package/lib/less-node/plugin-loader.js +0 -62
  131. package/lib/less-node/url-file-manager.js +0 -60
package/lib/less/utils.js DELETED
@@ -1,126 +0,0 @@
1
- /* jshint proto: true */
2
- import * as Constants from './constants.js';
3
- import { copy } from 'copy-anything';
4
-
5
- export function getLocation(index, inputStream) {
6
- let n = index + 1;
7
- let line = null;
8
- let column = -1;
9
-
10
- while (--n >= 0 && inputStream.charAt(n) !== '\n') {
11
- column++;
12
- }
13
-
14
- if (typeof index === 'number') {
15
- line = (inputStream.slice(0, index).match(/\n/g) || '').length;
16
- }
17
-
18
- return {
19
- line,
20
- column
21
- };
22
- }
23
-
24
- export function copyArray(arr) {
25
- let i;
26
- const length = arr.length;
27
- const copy = new Array(length);
28
-
29
- for (i = 0; i < length; i++) {
30
- copy[i] = arr[i];
31
- }
32
- return copy;
33
- }
34
-
35
- export function clone(obj) {
36
- const cloned = {};
37
- for (const prop in obj) {
38
- if (Object.prototype.hasOwnProperty.call(obj, prop)) {
39
- cloned[prop] = obj[prop];
40
- }
41
- }
42
- return cloned;
43
- }
44
-
45
- export function defaults(obj1, obj2) {
46
- let newObj = obj2 || {};
47
- if (!obj2._defaults) {
48
- newObj = {};
49
- const defaults = copy(obj1);
50
- newObj._defaults = defaults;
51
- const cloned = obj2 ? copy(obj2) : {};
52
- Object.assign(newObj, defaults, cloned);
53
- }
54
- return newObj;
55
- }
56
-
57
- export function copyOptions(obj1, obj2) {
58
- if (obj2 && obj2._defaults) {
59
- return obj2;
60
- }
61
- const opts = defaults(obj1, obj2);
62
- if (opts.strictMath) {
63
- opts.math = Constants.Math.PARENS;
64
- }
65
- // Back compat with changed relativeUrls option
66
- if (opts.relativeUrls) {
67
- opts.rewriteUrls = Constants.RewriteUrls.ALL;
68
- }
69
- if (typeof opts.math === 'string') {
70
- switch (opts.math.toLowerCase()) {
71
- case 'always':
72
- opts.math = Constants.Math.ALWAYS;
73
- break;
74
- case 'parens-division':
75
- opts.math = Constants.Math.PARENS_DIVISION;
76
- break;
77
- case 'strict':
78
- case 'parens':
79
- opts.math = Constants.Math.PARENS;
80
- break;
81
- default:
82
- opts.math = Constants.Math.PARENS;
83
- }
84
- }
85
- if (typeof opts.rewriteUrls === 'string') {
86
- switch (opts.rewriteUrls.toLowerCase()) {
87
- case 'off':
88
- opts.rewriteUrls = Constants.RewriteUrls.OFF;
89
- break;
90
- case 'local':
91
- opts.rewriteUrls = Constants.RewriteUrls.LOCAL;
92
- break;
93
- case 'all':
94
- opts.rewriteUrls = Constants.RewriteUrls.ALL;
95
- break;
96
- }
97
- }
98
- return opts;
99
- }
100
-
101
- export function merge(obj1, obj2) {
102
- for (const prop in obj2) {
103
- if (Object.prototype.hasOwnProperty.call(obj2, prop)) {
104
- obj1[prop] = obj2[prop];
105
- }
106
- }
107
- return obj1;
108
- }
109
-
110
- export function flattenArray(arr, result = []) {
111
- for (let i = 0, length = arr.length; i < length; i++) {
112
- const value = arr[i];
113
- if (Array.isArray(value)) {
114
- flattenArray(value, result);
115
- } else {
116
- if (value !== undefined) {
117
- result.push(value);
118
- }
119
- }
120
- }
121
- return result;
122
- }
123
-
124
- export function isNullOrUndefined(val) {
125
- return val === null || val === undefined
126
- }
@@ -1,505 +0,0 @@
1
- /* eslint-disable no-unused-vars */
2
- /**
3
- * @todo - Remove unused when JSDoc types are added for visitor methods
4
- */
5
- import tree from '../tree/index.js';
6
- import Visitor from './visitor.js';
7
- import logger from '../logger.js';
8
- import * as utils from '../utils.js';
9
-
10
- /* jshint loopfunc:true */
11
-
12
- class ExtendFinderVisitor {
13
- constructor() {
14
- this._visitor = new Visitor(this);
15
- this.contexts = [];
16
- this.allExtendsStack = [[]];
17
- }
18
-
19
- run(root) {
20
- root = this._visitor.visit(root);
21
- root.allExtends = this.allExtendsStack[0];
22
- return root;
23
- }
24
-
25
- visitDeclaration(declNode, visitArgs) {
26
- visitArgs.visitDeeper = false;
27
- }
28
-
29
- visitMixinDefinition(mixinDefinitionNode, visitArgs) {
30
- visitArgs.visitDeeper = false;
31
- }
32
-
33
- visitRuleset(rulesetNode, visitArgs) {
34
- if (rulesetNode.root) {
35
- return;
36
- }
37
-
38
- let i;
39
- let j;
40
- let extend;
41
- const allSelectorsExtendList = [];
42
- let extendList;
43
-
44
- // get &:extend(.a); rules which apply to all selectors in this ruleset
45
- const rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
46
- for (i = 0; i < ruleCnt; i++) {
47
- if (rulesetNode.rules[i] instanceof tree.Extend) {
48
- allSelectorsExtendList.push(rules[i]);
49
- rulesetNode.extendOnEveryPath = true;
50
- }
51
- }
52
-
53
- // now find every selector and apply the extends that apply to all extends
54
- // and the ones which apply to an individual extend
55
- const paths = rulesetNode.paths;
56
- for (i = 0; i < paths.length; i++) {
57
- const selectorPath = paths[i], selector = selectorPath[selectorPath.length - 1], selExtendList = selector.extendList;
58
-
59
- extendList = selExtendList ? utils.copyArray(selExtendList).concat(allSelectorsExtendList)
60
- : allSelectorsExtendList;
61
-
62
- if (extendList) {
63
- extendList = extendList.map(function(allSelectorsExtend) {
64
- return allSelectorsExtend.clone();
65
- });
66
- }
67
-
68
- for (j = 0; j < extendList.length; j++) {
69
- this.foundExtends = true;
70
- extend = extendList[j];
71
- extend.findSelfSelectors(selectorPath);
72
- extend.ruleset = rulesetNode;
73
- if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
74
- this.allExtendsStack[this.allExtendsStack.length - 1].push(extend);
75
- }
76
- }
77
-
78
- this.contexts.push(rulesetNode.selectors);
79
- }
80
-
81
- visitRulesetOut(rulesetNode) {
82
- if (!rulesetNode.root) {
83
- this.contexts.length = this.contexts.length - 1;
84
- }
85
- }
86
-
87
- visitMedia(mediaNode, visitArgs) {
88
- mediaNode.allExtends = [];
89
- this.allExtendsStack.push(mediaNode.allExtends);
90
- }
91
-
92
- visitMediaOut(mediaNode) {
93
- this.allExtendsStack.length = this.allExtendsStack.length - 1;
94
- }
95
-
96
- visitAtRule(atRuleNode, visitArgs) {
97
- atRuleNode.allExtends = [];
98
- this.allExtendsStack.push(atRuleNode.allExtends);
99
- }
100
-
101
- visitAtRuleOut(atRuleNode) {
102
- this.allExtendsStack.length = this.allExtendsStack.length - 1;
103
- }
104
- }
105
-
106
- class ProcessExtendsVisitor {
107
- constructor() {
108
- this._visitor = new Visitor(this);
109
- }
110
-
111
- run(root) {
112
- const extendFinder = new ExtendFinderVisitor();
113
- this.extendIndices = {};
114
- extendFinder.run(root);
115
- if (!extendFinder.foundExtends) { return root; }
116
- root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
117
- this.allExtendsStack = [root.allExtends];
118
- const newRoot = this._visitor.visit(root);
119
- this.checkExtendsForNonMatched(root.allExtends);
120
- return newRoot;
121
- }
122
-
123
- checkExtendsForNonMatched(extendList) {
124
- const indices = this.extendIndices;
125
- extendList.filter(function(extend) {
126
- return !extend.hasFoundMatches && extend.parent_ids.length == 1;
127
- }).forEach(function(extend) {
128
- let selector = '_unknown_';
129
- try {
130
- selector = extend.selector.toCSS({});
131
- }
132
- catch (_) {}
133
-
134
- if (!indices[`${extend.index} ${selector}`]) {
135
- indices[`${extend.index} ${selector}`] = true;
136
- /**
137
- * @todo Shouldn't this be an error? To alert the developer
138
- * that they may have made an error in the selector they are
139
- * targeting?
140
- */
141
- logger.warn(`WARNING: extend '${selector}' has no matches`);
142
- }
143
- });
144
- }
145
-
146
- doExtendChaining(extendsList, extendsListTarget, iterationCount) {
147
- //
148
- // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering
149
- // and pasting the selector we would do normally, but we are also adding an extend with the same target selector
150
- // this means this new extend can then go and alter other extends
151
- //
152
- // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
153
- // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already
154
- // processed if we look at each selector at a time, as is done in visitRuleset
155
-
156
- let extendIndex;
157
-
158
- let targetExtendIndex;
159
- let matches;
160
- const extendsToAdd = [];
161
- let newSelector;
162
- const extendVisitor = this;
163
- let selectorPath;
164
- let extend;
165
- let targetExtend;
166
- let newExtend;
167
-
168
- iterationCount = iterationCount || 0;
169
-
170
- // loop through comparing every extend with every target extend.
171
- // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
172
- // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
173
- // and the second is the target.
174
- // the separation into two lists allows us to process a subset of chains with a bigger set, as is the
175
- // case when processing media queries
176
- for (extendIndex = 0; extendIndex < extendsList.length; extendIndex++) {
177
- for (targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++) {
178
-
179
- extend = extendsList[extendIndex];
180
- targetExtend = extendsListTarget[targetExtendIndex];
181
-
182
- // look for circular references
183
- if ( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ) { continue; }
184
-
185
- // find a match in the target extends self selector (the bit before :extend)
186
- selectorPath = [targetExtend.selfSelectors[0]];
187
- matches = extendVisitor.findMatch(extend, selectorPath);
188
-
189
- if (matches.length) {
190
- extend.hasFoundMatches = true;
191
-
192
- // we found a match, so for each self selector..
193
- extend.selfSelectors.forEach(function(selfSelector) {
194
- const info = targetExtend.visibilityInfo();
195
-
196
- // process the extend as usual
197
- newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector, extend.isVisible());
198
-
199
- // but now we create a new extend from it
200
- newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.fileInfo(), info);
201
- newExtend.selfSelectors = newSelector;
202
-
203
- // add the extend onto the list of extends for that selector
204
- newSelector[newSelector.length - 1].extendList = [newExtend];
205
-
206
- // record that we need to add it.
207
- extendsToAdd.push(newExtend);
208
- newExtend.ruleset = targetExtend.ruleset;
209
-
210
- // remember its parents for circular references
211
- newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
212
-
213
- // only process the selector once.. if we have :extend(.a,.b) then multiple
214
- // extends will look at the same selector path, so when extending
215
- // we know that any others will be duplicates in terms of what is added to the css
216
- if (targetExtend.firstExtendOnThisSelectorPath) {
217
- newExtend.firstExtendOnThisSelectorPath = true;
218
- targetExtend.ruleset.paths.push(newSelector);
219
- }
220
- });
221
- }
222
- }
223
- }
224
-
225
- if (extendsToAdd.length) {
226
- // try to detect circular references to stop a stack overflow.
227
- // may no longer be needed.
228
- this.extendChainCount++;
229
- if (iterationCount > 100) {
230
- let selectorOne = '{unable to calculate}';
231
- let selectorTwo = '{unable to calculate}';
232
- try {
233
- selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
234
- selectorTwo = extendsToAdd[0].selector.toCSS();
235
- }
236
- catch (e) {}
237
- throw { message: `extend circular reference detected. One of the circular extends is currently:${selectorOne}:extend(${selectorTwo})`};
238
- }
239
-
240
- // now process the new extends on the existing rules so that we can handle a extending b extending c extending
241
- // d extending e...
242
- return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount + 1));
243
- } else {
244
- return extendsToAdd;
245
- }
246
- }
247
-
248
- visitDeclaration(ruleNode, visitArgs) {
249
- visitArgs.visitDeeper = false;
250
- }
251
-
252
- visitMixinDefinition(mixinDefinitionNode, visitArgs) {
253
- visitArgs.visitDeeper = false;
254
- }
255
-
256
- visitSelector(selectorNode, visitArgs) {
257
- visitArgs.visitDeeper = false;
258
- }
259
-
260
- visitRuleset(rulesetNode, visitArgs) {
261
- if (rulesetNode.root) {
262
- return;
263
- }
264
- let matches;
265
- const allExtends = this.allExtendsStack[this.allExtendsStack.length - 1];
266
- const selectorsToAdd = [];
267
- const paths = rulesetNode.paths;
268
- const pathCount = paths.length;
269
-
270
- // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
271
-
272
- for (let extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
273
- const extend = allExtends[extendIndex];
274
- for (let pathIndex = 0; pathIndex < pathCount; pathIndex++) {
275
- const selectorPath = paths[pathIndex];
276
-
277
- // extending extends happens initially, before the main pass
278
- if (rulesetNode.extendOnEveryPath) { continue; }
279
- const extendList = selectorPath[selectorPath.length - 1].extendList;
280
- if (extendList && extendList.length) { continue; }
281
-
282
- matches = this.findMatch(extend, selectorPath);
283
-
284
- if (matches.length) {
285
- extend.hasFoundMatches = true;
286
-
287
- const selfSelectors = extend.selfSelectors;
288
- const isVisible = extend.isVisible();
289
- for (let si = 0; si < selfSelectors.length; si++) {
290
- selectorsToAdd.push(this.extendSelector(matches, selectorPath, selfSelectors[si], isVisible));
291
- }
292
- }
293
- }
294
- }
295
- rulesetNode.paths = paths.concat(selectorsToAdd);
296
- }
297
-
298
- findMatch(extend, haystackSelectorPath) {
299
- //
300
- // look through the haystack selector path to try and find the needle - extend.selector
301
- // returns an array of selector matches that can then be replaced
302
- //
303
- let haystackSelectorIndex;
304
-
305
- let hackstackSelector;
306
- let hackstackElementIndex;
307
- let haystackElement;
308
- let targetCombinator;
309
- let i;
310
- const needleElements = extend.selector.elements;
311
- const potentialMatches = [];
312
- let potentialMatch;
313
- const matches = [];
314
-
315
- // loop through the haystack elements
316
- for (haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
317
- hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
318
-
319
- for (hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
320
-
321
- haystackElement = hackstackSelector.elements[hackstackElementIndex];
322
-
323
- // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
324
- if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
325
- potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0,
326
- initialCombinator: haystackElement.combinator});
327
- }
328
-
329
- for (i = 0; i < potentialMatches.length; i++) {
330
- potentialMatch = potentialMatches[i];
331
-
332
- // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
333
- // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to
334
- // work out what the resulting combinator will be
335
- targetCombinator = haystackElement.combinator.value;
336
- if (targetCombinator === '' && hackstackElementIndex === 0) {
337
- targetCombinator = ' ';
338
- }
339
-
340
- // if we don't match, null our match to indicate failure
341
- if (!this.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) ||
342
- (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) {
343
- potentialMatch = null;
344
- } else {
345
- potentialMatch.matched++;
346
- }
347
-
348
- // if we are still valid and have finished, test whether we have elements after and whether these are allowed
349
- if (potentialMatch) {
350
- potentialMatch.finished = potentialMatch.matched === needleElements.length;
351
- if (potentialMatch.finished &&
352
- (!extend.allowAfter &&
353
- (hackstackElementIndex + 1 < hackstackSelector.elements.length || haystackSelectorIndex + 1 < haystackSelectorPath.length))) {
354
- potentialMatch = null;
355
- }
356
- }
357
- // if null we remove, if not, we are still valid, so either push as a valid match or continue
358
- if (potentialMatch) {
359
- if (potentialMatch.finished) {
360
- potentialMatch.length = needleElements.length;
361
- potentialMatch.endPathIndex = haystackSelectorIndex;
362
- potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match
363
- potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again
364
- matches.push(potentialMatch);
365
- }
366
- } else {
367
- potentialMatches.splice(i, 1);
368
- i--;
369
- }
370
- }
371
- }
372
- }
373
- return matches;
374
- }
375
-
376
- isElementValuesEqual(elementValue1, elementValue2) {
377
- if (typeof elementValue1 === 'string' || typeof elementValue2 === 'string') {
378
- return elementValue1 === elementValue2;
379
- }
380
- if (elementValue1 instanceof tree.Attribute) {
381
- if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) {
382
- return false;
383
- }
384
- if (!elementValue1.value || !elementValue2.value) {
385
- if (elementValue1.value || elementValue2.value) {
386
- return false;
387
- }
388
- return true;
389
- }
390
- elementValue1 = elementValue1.value.value || elementValue1.value;
391
- elementValue2 = elementValue2.value.value || elementValue2.value;
392
- return elementValue1 === elementValue2;
393
- }
394
- elementValue1 = elementValue1.value;
395
- elementValue2 = elementValue2.value;
396
- if (elementValue1 instanceof tree.Selector) {
397
- if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
398
- return false;
399
- }
400
- for (let i = 0; i < elementValue1.elements.length; i++) {
401
- if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
402
- if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
403
- return false;
404
- }
405
- }
406
- if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) {
407
- return false;
408
- }
409
- }
410
- return true;
411
- }
412
- return false;
413
- }
414
-
415
- extendSelector(matches, selectorPath, replacementSelector, isVisible) {
416
-
417
- // for a set of matches, replace each match with the replacement selector
418
-
419
- let currentSelectorPathIndex = 0, currentSelectorPathElementIndex = 0, path = [], matchIndex, selector, firstElement, match, newElements;
420
-
421
- for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
422
- match = matches[matchIndex];
423
- selector = selectorPath[match.pathIndex];
424
- firstElement = new tree.Element(
425
- match.initialCombinator,
426
- replacementSelector.elements[0].value,
427
- replacementSelector.elements[0].isVariable,
428
- replacementSelector.elements[0].getIndex(),
429
- replacementSelector.elements[0].fileInfo()
430
- );
431
-
432
- if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
433
- path[path.length - 1].elements = path[path.length - 1]
434
- .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
435
- currentSelectorPathElementIndex = 0;
436
- currentSelectorPathIndex++;
437
- }
438
-
439
- newElements = selector.elements
440
- .slice(currentSelectorPathElementIndex, match.index)
441
- .concat([firstElement])
442
- .concat(replacementSelector.elements.slice(1));
443
-
444
- if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
445
- path[path.length - 1].elements =
446
- path[path.length - 1].elements.concat(newElements);
447
- } else {
448
- path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
449
-
450
- path.push(new tree.Selector(
451
- newElements
452
- ));
453
- }
454
- currentSelectorPathIndex = match.endPathIndex;
455
- currentSelectorPathElementIndex = match.endPathElementIndex;
456
- if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
457
- currentSelectorPathElementIndex = 0;
458
- currentSelectorPathIndex++;
459
- }
460
- }
461
-
462
- if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
463
- path[path.length - 1].elements = path[path.length - 1]
464
- .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
465
- currentSelectorPathIndex++;
466
- }
467
-
468
- path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
469
- path = path.map(function (currentValue) {
470
- // we can re-use elements here, because the visibility property matters only for selectors
471
- const derived = currentValue.createDerived(currentValue.elements);
472
- if (isVisible) {
473
- derived.ensureVisibility();
474
- } else {
475
- derived.ensureInvisibility();
476
- }
477
- return derived;
478
- });
479
- return path;
480
- }
481
-
482
- visitMedia(mediaNode, visitArgs) {
483
- let newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
484
- newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
485
- this.allExtendsStack.push(newAllExtends);
486
- }
487
-
488
- visitMediaOut(mediaNode) {
489
- const lastIndex = this.allExtendsStack.length - 1;
490
- this.allExtendsStack.length = lastIndex;
491
- }
492
-
493
- visitAtRule(atRuleNode, visitArgs) {
494
- let newAllExtends = atRuleNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
495
- newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, atRuleNode.allExtends));
496
- this.allExtendsStack.push(newAllExtends);
497
- }
498
-
499
- visitAtRuleOut(atRuleNode) {
500
- const lastIndex = this.allExtendsStack.length - 1;
501
- this.allExtendsStack.length = lastIndex;
502
- }
503
- }
504
-
505
- export default ProcessExtendsVisitor;
@@ -1,56 +0,0 @@
1
- class ImportSequencer {
2
- constructor(onSequencerEmpty) {
3
- this.imports = [];
4
- this.variableImports = [];
5
- this._onSequencerEmpty = onSequencerEmpty;
6
- this._currentDepth = 0;
7
- }
8
-
9
- addImport(callback) {
10
- const importSequencer = this,
11
- importItem = {
12
- callback,
13
- args: null,
14
- isReady: false
15
- };
16
- this.imports.push(importItem);
17
- return function() {
18
- importItem.args = Array.prototype.slice.call(arguments, 0);
19
- importItem.isReady = true;
20
- importSequencer.tryRun();
21
- };
22
- }
23
-
24
- addVariableImport(callback) {
25
- this.variableImports.push(callback);
26
- }
27
-
28
- tryRun() {
29
- this._currentDepth++;
30
- try {
31
- while (true) {
32
- while (this.imports.length > 0) {
33
- const importItem = this.imports[0];
34
- if (!importItem.isReady) {
35
- return;
36
- }
37
- this.imports = this.imports.slice(1);
38
- importItem.callback.apply(null, importItem.args);
39
- }
40
- if (this.variableImports.length === 0) {
41
- break;
42
- }
43
- const variableImport = this.variableImports[0];
44
- this.variableImports = this.variableImports.slice(1);
45
- variableImport();
46
- }
47
- } finally {
48
- this._currentDepth--;
49
- }
50
- if (this._currentDepth === 0 && this._onSequencerEmpty) {
51
- this._onSequencerEmpty();
52
- }
53
- }
54
- }
55
-
56
- export default ImportSequencer;