less 3.10.0-beta.2 → 3.10.3

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 (124) hide show
  1. package/.DS_Store +0 -0
  2. package/bin/lessc +6652 -5505
  3. package/dist/less.cjs.js +6593 -5448
  4. package/dist/less.js +10 -6
  5. package/dist/less.min.js +2 -2
  6. package/dist/less.min.js.map +1 -1
  7. package/lib/less/constants.js +13 -0
  8. package/lib/less/contexts.js +164 -0
  9. package/lib/less/data/colors.js +150 -0
  10. package/lib/less/data/index.js +4 -0
  11. package/lib/less/data/unit-conversions.js +21 -0
  12. package/lib/less/default-options.js +68 -0
  13. package/lib/less/environment/abstract-file-manager.js +127 -0
  14. package/lib/less/environment/abstract-plugin-loader.js +187 -0
  15. package/lib/less/environment/environment-api.js +25 -0
  16. package/lib/less/environment/environment.js +59 -0
  17. package/lib/less/environment/file-manager-api.js +103 -0
  18. package/lib/less/functions/boolean.js +13 -0
  19. package/lib/less/functions/color-blending.js +84 -0
  20. package/lib/less/functions/color.js +417 -0
  21. package/lib/less/functions/data-uri.js +74 -0
  22. package/lib/less/functions/default.js +25 -0
  23. package/lib/less/functions/function-caller.js +49 -0
  24. package/lib/less/functions/function-registry.js +35 -0
  25. package/lib/less/functions/index.js +33 -0
  26. package/lib/less/functions/list.js +143 -0
  27. package/lib/less/functions/math-helper.js +15 -0
  28. package/lib/less/functions/math.js +28 -0
  29. package/lib/less/functions/number.js +89 -0
  30. package/lib/less/functions/string.js +36 -0
  31. package/lib/less/functions/svg.js +87 -0
  32. package/lib/less/functions/types.js +70 -0
  33. package/lib/less/import-manager.js +169 -0
  34. package/lib/less/index.js +92 -0
  35. package/lib/less/less-error.js +140 -0
  36. package/lib/less/logger.js +34 -0
  37. package/lib/less/parse-tree.js +66 -0
  38. package/lib/less/parse.js +89 -0
  39. package/lib/less/parser/chunker.js +122 -0
  40. package/lib/less/parser/parser-input.js +390 -0
  41. package/lib/less/parser/parser.js +2418 -0
  42. package/lib/less/plugin-manager.js +168 -0
  43. package/lib/less/render.js +42 -0
  44. package/lib/less/source-map-builder.js +77 -0
  45. package/lib/less/source-map-output.js +149 -0
  46. package/lib/less/transform-tree.js +96 -0
  47. package/lib/less/tree/anonymous.js +37 -0
  48. package/lib/less/tree/assignment.js +33 -0
  49. package/lib/less/tree/atrule.js +165 -0
  50. package/lib/less/tree/attribute.js +34 -0
  51. package/lib/less/tree/call.js +105 -0
  52. package/lib/less/tree/color.js +246 -0
  53. package/lib/less/tree/combinator.js +29 -0
  54. package/lib/less/tree/comment.js +29 -0
  55. package/lib/less/tree/condition.js +43 -0
  56. package/lib/less/tree/debug-info.js +34 -0
  57. package/lib/less/tree/declaration.js +115 -0
  58. package/lib/less/tree/detached-ruleset.js +30 -0
  59. package/lib/less/tree/dimension.js +179 -0
  60. package/lib/less/tree/element.js +73 -0
  61. package/lib/less/tree/expression.js +74 -0
  62. package/lib/less/tree/extend.js +66 -0
  63. package/lib/less/tree/import.js +184 -0
  64. package/lib/less/tree/index.js +54 -0
  65. package/lib/less/tree/javascript.js +33 -0
  66. package/lib/less/tree/js-eval-node.js +58 -0
  67. package/lib/less/tree/keyword.js +21 -0
  68. package/lib/less/tree/media.js +154 -0
  69. package/lib/less/tree/mixin-call.js +215 -0
  70. package/lib/less/tree/mixin-definition.js +229 -0
  71. package/lib/less/tree/namespace-value.js +87 -0
  72. package/lib/less/tree/negative.js +26 -0
  73. package/lib/less/tree/node.js +178 -0
  74. package/lib/less/tree/operation.js +62 -0
  75. package/lib/less/tree/paren.js +22 -0
  76. package/lib/less/tree/property.js +77 -0
  77. package/lib/less/tree/quoted.js +70 -0
  78. package/lib/less/tree/ruleset.js +867 -0
  79. package/lib/less/tree/selector.js +146 -0
  80. package/lib/less/tree/unicode-descriptor.js +13 -0
  81. package/lib/less/tree/unit.js +141 -0
  82. package/lib/less/tree/url.js +65 -0
  83. package/lib/less/tree/value.js +44 -0
  84. package/lib/less/tree/variable-call.js +46 -0
  85. package/lib/less/tree/variable.js +67 -0
  86. package/lib/less/utils.js +122 -0
  87. package/lib/less/visitors/extend-visitor.js +505 -0
  88. package/lib/less/visitors/import-sequencer.js +58 -0
  89. package/lib/less/visitors/import-visitor.js +189 -0
  90. package/lib/less/visitors/index.js +15 -0
  91. package/lib/less/visitors/join-selector-visitor.js +57 -0
  92. package/lib/less/visitors/set-tree-visibility-visitor.js +45 -0
  93. package/lib/less/visitors/to-css-visitor.js +363 -0
  94. package/lib/less/visitors/visitor.js +163 -0
  95. package/lib/less-browser/add-default-options.js +49 -0
  96. package/lib/less-browser/bootstrap.js +69 -0
  97. package/lib/less-browser/browser.js +65 -0
  98. package/lib/less-browser/cache.js +43 -0
  99. package/lib/less-browser/error-reporting.js +170 -0
  100. package/lib/less-browser/file-manager.js +113 -0
  101. package/lib/less-browser/image-size.js +28 -0
  102. package/lib/less-browser/index.js +285 -0
  103. package/lib/less-browser/log-listener.js +42 -0
  104. package/lib/less-browser/plugin-loader.js +26 -0
  105. package/lib/less-browser/utils.js +24 -0
  106. package/lib/less-node/environment.js +16 -0
  107. package/lib/less-node/file-manager.js +177 -0
  108. package/lib/less-node/fs.js +10 -0
  109. package/lib/less-node/image-size.js +58 -0
  110. package/lib/less-node/index.js +27 -0
  111. package/lib/less-node/lessc-helper.js +89 -0
  112. package/lib/less-node/plugin-loader.js +53 -0
  113. package/lib/less-node/url-file-manager.js +49 -0
  114. package/lib/lessc.js +557 -0
  115. package/lib/source-map/source-map-0.1.31.js +1933 -0
  116. package/lib/source-map/source-map-footer.js +4 -0
  117. package/lib/source-map/source-map-header.js +3 -0
  118. package/package.json +1 -1
  119. package/test/.DS_Store +0 -0
  120. package/test/browser/less.min.js +11 -0
  121. package/test/browser/less.min.js.map +1 -0
  122. package/test/css/css-escapes.css +1 -0
  123. package/test/less/css-escapes.less +3 -1
  124. package/.git/index +0 -0
@@ -0,0 +1,165 @@
1
+ import Node from './node';
2
+ import Selector from './selector';
3
+ import Ruleset from './ruleset';
4
+ import Anonymous from './anonymous';
5
+
6
+ class AtRule extends Node {
7
+ constructor(
8
+ name,
9
+ value,
10
+ rules,
11
+ index,
12
+ currentFileInfo,
13
+ debugInfo,
14
+ isRooted,
15
+ visibilityInfo
16
+ ) {
17
+ super();
18
+
19
+ let i;
20
+
21
+ this.name = name;
22
+ this.value = (value instanceof Node) ? value : (value ? new Anonymous(value) : value);
23
+ if (rules) {
24
+ if (Array.isArray(rules)) {
25
+ this.rules = rules;
26
+ } else {
27
+ this.rules = [rules];
28
+ this.rules[0].selectors = (new Selector([], null, null, index, currentFileInfo)).createEmptySelectors();
29
+ }
30
+ for (i = 0; i < this.rules.length; i++) {
31
+ this.rules[i].allowImports = true;
32
+ }
33
+ this.setParent(this.rules, this);
34
+ }
35
+ this._index = index;
36
+ this._fileInfo = currentFileInfo;
37
+ this.debugInfo = debugInfo;
38
+ this.isRooted = isRooted || false;
39
+ this.copyVisibilityInfo(visibilityInfo);
40
+ this.allowRoot = true;
41
+ }
42
+
43
+ accept(visitor) {
44
+ const value = this.value;
45
+ const rules = this.rules;
46
+ if (rules) {
47
+ this.rules = visitor.visitArray(rules);
48
+ }
49
+ if (value) {
50
+ this.value = visitor.visit(value);
51
+ }
52
+ }
53
+
54
+ isRulesetLike() {
55
+ return this.rules || !this.isCharset();
56
+ }
57
+
58
+ isCharset() {
59
+ return '@charset' === this.name;
60
+ }
61
+
62
+ genCSS(context, output) {
63
+ const value = this.value;
64
+ const rules = this.rules;
65
+ output.add(this.name, this.fileInfo(), this.getIndex());
66
+ if (value) {
67
+ output.add(' ');
68
+ value.genCSS(context, output);
69
+ }
70
+ if (rules) {
71
+ this.outputRuleset(context, output, rules);
72
+ } else {
73
+ output.add(';');
74
+ }
75
+ }
76
+
77
+ eval(context) {
78
+ let mediaPathBackup;
79
+ let mediaBlocksBackup;
80
+ let value = this.value;
81
+ let rules = this.rules;
82
+
83
+ // media stored inside other atrule should not bubble over it
84
+ // backpup media bubbling information
85
+ mediaPathBackup = context.mediaPath;
86
+ mediaBlocksBackup = context.mediaBlocks;
87
+ // deleted media bubbling information
88
+ context.mediaPath = [];
89
+ context.mediaBlocks = [];
90
+
91
+ if (value) {
92
+ value = value.eval(context);
93
+ }
94
+ if (rules) {
95
+ // assuming that there is only one rule at this point - that is how parser constructs the rule
96
+ rules = [rules[0].eval(context)];
97
+ rules[0].root = true;
98
+ }
99
+ // restore media bubbling information
100
+ context.mediaPath = mediaPathBackup;
101
+ context.mediaBlocks = mediaBlocksBackup;
102
+
103
+ return new AtRule(this.name, value, rules,
104
+ this.getIndex(), this.fileInfo(), this.debugInfo, this.isRooted, this.visibilityInfo());
105
+ }
106
+
107
+ variable(name) {
108
+ if (this.rules) {
109
+ // assuming that there is only one rule at this point - that is how parser constructs the rule
110
+ return Ruleset.prototype.variable.call(this.rules[0], name);
111
+ }
112
+ }
113
+
114
+ find(...args) {
115
+ if (this.rules) {
116
+ // assuming that there is only one rule at this point - that is how parser constructs the rule
117
+ return Ruleset.prototype.find.apply(this.rules[0], args);
118
+ }
119
+ }
120
+
121
+ rulesets() {
122
+ if (this.rules) {
123
+ // assuming that there is only one rule at this point - that is how parser constructs the rule
124
+ return Ruleset.prototype.rulesets.apply(this.rules[0]);
125
+ }
126
+ }
127
+
128
+ outputRuleset(context, output, rules) {
129
+ const ruleCnt = rules.length;
130
+ let i;
131
+ context.tabLevel = (context.tabLevel | 0) + 1;
132
+
133
+ // Compressed
134
+ if (context.compress) {
135
+ output.add('{');
136
+ for (i = 0; i < ruleCnt; i++) {
137
+ rules[i].genCSS(context, output);
138
+ }
139
+ output.add('}');
140
+ context.tabLevel--;
141
+ return;
142
+ }
143
+
144
+ // Non-compressed
145
+ const tabSetStr = `\n${Array(context.tabLevel).join(' ')}`;
146
+
147
+ const tabRuleStr = `${tabSetStr} `;
148
+ if (!ruleCnt) {
149
+ output.add(` {${tabSetStr}}`);
150
+ } else {
151
+ output.add(` {${tabRuleStr}`);
152
+ rules[0].genCSS(context, output);
153
+ for (i = 1; i < ruleCnt; i++) {
154
+ output.add(tabRuleStr);
155
+ rules[i].genCSS(context, output);
156
+ }
157
+ output.add(`${tabSetStr}}`);
158
+ }
159
+
160
+ context.tabLevel--;
161
+ }
162
+ }
163
+
164
+ AtRule.prototype.type = 'AtRule';
165
+ export default AtRule;
@@ -0,0 +1,34 @@
1
+ import Node from './node';
2
+
3
+ class Attribute extends Node {
4
+ constructor(key, op, value) {
5
+ super();
6
+
7
+ this.key = key;
8
+ this.op = op;
9
+ this.value = value;
10
+ }
11
+
12
+ eval(context) {
13
+ return new Attribute(this.key.eval ? this.key.eval(context) : this.key,
14
+ this.op, (this.value && this.value.eval) ? this.value.eval(context) : this.value);
15
+ }
16
+
17
+ genCSS(context, output) {
18
+ output.add(this.toCSS(context));
19
+ }
20
+
21
+ toCSS(context) {
22
+ let value = this.key.toCSS ? this.key.toCSS(context) : this.key;
23
+
24
+ if (this.op) {
25
+ value += this.op;
26
+ value += (this.value.toCSS ? this.value.toCSS(context) : this.value);
27
+ }
28
+
29
+ return `[${value}]`;
30
+ }
31
+ }
32
+
33
+ Attribute.prototype.type = 'Attribute';
34
+ export default Attribute;
@@ -0,0 +1,105 @@
1
+ import Node from './node';
2
+ import Anonymous from './anonymous';
3
+ import FunctionCaller from '../functions/function-caller';
4
+
5
+ //
6
+ // A function call node.
7
+ //
8
+ class Call extends Node {
9
+ constructor(name, args, index, currentFileInfo) {
10
+ super();
11
+
12
+ this.name = name;
13
+ this.args = args;
14
+ this.calc = name === 'calc';
15
+ this._index = index;
16
+ this._fileInfo = currentFileInfo;
17
+ }
18
+
19
+ accept(visitor) {
20
+ if (this.args) {
21
+ this.args = visitor.visitArray(this.args);
22
+ }
23
+ }
24
+
25
+ //
26
+ // When evaluating a function call,
27
+ // we either find the function in the functionRegistry,
28
+ // in which case we call it, passing the evaluated arguments,
29
+ // if this returns null or we cannot find the function, we
30
+ // simply print it out as it appeared originally [2].
31
+ //
32
+ // The reason why we evaluate the arguments, is in the case where
33
+ // we try to pass a variable to a function, like: `saturate(@color)`.
34
+ // The function should receive the value, not the variable.
35
+ //
36
+ eval(context) {
37
+ /**
38
+ * Turn off math for calc(), and switch back on for evaluating nested functions
39
+ */
40
+ const currentMathContext = context.mathOn;
41
+ context.mathOn = !this.calc;
42
+ if (this.calc || context.inCalc) {
43
+ context.enterCalc();
44
+ }
45
+ const args = this.args.map(a => a.eval(context));
46
+ if (this.calc || context.inCalc) {
47
+ context.exitCalc();
48
+ }
49
+ context.mathOn = currentMathContext;
50
+
51
+ let result;
52
+ const funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo());
53
+
54
+ if (funcCaller.isValid()) {
55
+ try {
56
+ result = funcCaller.call(args);
57
+ } catch (e) {
58
+ throw {
59
+ type: e.type || 'Runtime',
60
+ message: `error evaluating function \`${this.name}\`${e.message ? `: ${e.message}` : ''}`,
61
+ index: this.getIndex(),
62
+ filename: this.fileInfo().filename,
63
+ line: e.lineNumber,
64
+ column: e.columnNumber
65
+ };
66
+ }
67
+
68
+ if (result !== null && result !== undefined) {
69
+ // Results that that are not nodes are cast as Anonymous nodes
70
+ // Falsy values or booleans are returned as empty nodes
71
+ if (!(result instanceof Node)) {
72
+ if (!result || result === true) {
73
+ result = new Anonymous(null);
74
+ }
75
+ else {
76
+ result = new Anonymous(result.toString());
77
+ }
78
+
79
+ }
80
+ result._index = this._index;
81
+ result._fileInfo = this._fileInfo;
82
+ return result;
83
+ }
84
+
85
+ }
86
+
87
+ return new Call(this.name, args, this.getIndex(), this.fileInfo());
88
+ }
89
+
90
+ genCSS(context, output) {
91
+ output.add(`${this.name}(`, this.fileInfo(), this.getIndex());
92
+
93
+ for (let i = 0; i < this.args.length; i++) {
94
+ this.args[i].genCSS(context, output);
95
+ if (i + 1 < this.args.length) {
96
+ output.add(', ');
97
+ }
98
+ }
99
+
100
+ output.add(')');
101
+ }
102
+ }
103
+
104
+ Call.prototype.type = 'Call';
105
+ export default Call;
@@ -0,0 +1,246 @@
1
+ import Node from './node';
2
+ import colors from '../data/colors';
3
+
4
+ //
5
+ // RGB Colors - #ff0014, #eee
6
+ //
7
+ class Color extends Node {
8
+ constructor(rgb, a, originalForm) {
9
+ super();
10
+
11
+ const self = this;
12
+ //
13
+ // The end goal here, is to parse the arguments
14
+ // into an integer triplet, such as `128, 255, 0`
15
+ //
16
+ // This facilitates operations and conversions.
17
+ //
18
+ if (Array.isArray(rgb)) {
19
+ this.rgb = rgb;
20
+ } else if (rgb.length >= 6) {
21
+ this.rgb = [];
22
+ rgb.match(/.{2}/g).map((c, i) => {
23
+ if (i < 3) {
24
+ self.rgb.push(parseInt(c, 16));
25
+ } else {
26
+ self.alpha = (parseInt(c, 16)) / 255;
27
+ }
28
+ });
29
+ } else {
30
+ this.rgb = [];
31
+ rgb.split('').map((c, i) => {
32
+ if (i < 3) {
33
+ self.rgb.push(parseInt(c + c, 16));
34
+ } else {
35
+ self.alpha = (parseInt(c + c, 16)) / 255;
36
+ }
37
+ });
38
+ }
39
+ this.alpha = this.alpha || (typeof a === 'number' ? a : 1);
40
+ if (typeof originalForm !== 'undefined') {
41
+ this.value = originalForm;
42
+ }
43
+ }
44
+
45
+ luma() {
46
+ let r = this.rgb[0] / 255;
47
+ let g = this.rgb[1] / 255;
48
+ let b = this.rgb[2] / 255;
49
+
50
+ r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
51
+ g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
52
+ b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
53
+
54
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
55
+ }
56
+
57
+ genCSS(context, output) {
58
+ output.add(this.toCSS(context));
59
+ }
60
+
61
+ toCSS(context, doNotCompress) {
62
+ const compress = context && context.compress && !doNotCompress;
63
+ let color;
64
+ let alpha;
65
+ let colorFunction;
66
+ let args = [];
67
+
68
+ // `value` is set if this color was originally
69
+ // converted from a named color string so we need
70
+ // to respect this and try to output named color too.
71
+ alpha = this.fround(context, this.alpha);
72
+
73
+ if (this.value) {
74
+ if (this.value.indexOf('rgb') === 0) {
75
+ if (alpha < 1) {
76
+ colorFunction = 'rgba';
77
+ }
78
+ } else if (this.value.indexOf('hsl') === 0) {
79
+ if (alpha < 1) {
80
+ colorFunction = 'hsla';
81
+ } else {
82
+ colorFunction = 'hsl';
83
+ }
84
+ } else {
85
+ return this.value;
86
+ }
87
+ } else {
88
+ if (alpha < 1) {
89
+ colorFunction = 'rgba';
90
+ }
91
+ }
92
+
93
+ switch (colorFunction) {
94
+ case 'rgba':
95
+ args = this.rgb.map(c => clamp(Math.round(c), 255)).concat(clamp(alpha, 1));
96
+ break;
97
+ case 'hsla':
98
+ args.push(clamp(alpha, 1));
99
+ case 'hsl':
100
+ color = this.toHSL();
101
+ args = [
102
+ this.fround(context, color.h),
103
+ `${this.fround(context, color.s * 100)}%`,
104
+ `${this.fround(context, color.l * 100)}%`
105
+ ].concat(args);
106
+ }
107
+
108
+ if (colorFunction) {
109
+ // Values are capped between `0` and `255`, rounded and zero-padded.
110
+ return `${colorFunction}(${args.join(`,${compress ? '' : ' '}`)})`;
111
+ }
112
+
113
+ color = this.toRGB();
114
+
115
+ if (compress) {
116
+ const splitcolor = color.split('');
117
+
118
+ // Convert color to short format
119
+ if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) {
120
+ color = `#${splitcolor[1]}${splitcolor[3]}${splitcolor[5]}`;
121
+ }
122
+ }
123
+
124
+ return color;
125
+ }
126
+
127
+ //
128
+ // Operations have to be done per-channel, if not,
129
+ // channels will spill onto each other. Once we have
130
+ // our result, in the form of an integer triplet,
131
+ // we create a new Color node to hold the result.
132
+ //
133
+ operate(context, op, other) {
134
+ const rgb = new Array(3);
135
+ const alpha = this.alpha * (1 - other.alpha) + other.alpha;
136
+ for (let c = 0; c < 3; c++) {
137
+ rgb[c] = this._operate(context, op, this.rgb[c], other.rgb[c]);
138
+ }
139
+ return new Color(rgb, alpha);
140
+ }
141
+
142
+ toRGB() {
143
+ return toHex(this.rgb);
144
+ }
145
+
146
+ toHSL() {
147
+ const r = this.rgb[0] / 255;
148
+ const g = this.rgb[1] / 255;
149
+ const b = this.rgb[2] / 255;
150
+ const a = this.alpha;
151
+ const max = Math.max(r, g, b);
152
+ const min = Math.min(r, g, b);
153
+ let h;
154
+ let s;
155
+ const l = (max + min) / 2;
156
+ const d = max - min;
157
+
158
+ if (max === min) {
159
+ h = s = 0;
160
+ } else {
161
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
162
+
163
+ switch (max) {
164
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
165
+ case g: h = (b - r) / d + 2; break;
166
+ case b: h = (r - g) / d + 4; break;
167
+ }
168
+ h /= 6;
169
+ }
170
+ return { h: h * 360, s, l, a };
171
+ }
172
+
173
+ // Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
174
+ toHSV() {
175
+ const r = this.rgb[0] / 255;
176
+ const g = this.rgb[1] / 255;
177
+ const b = this.rgb[2] / 255;
178
+ const a = this.alpha;
179
+ const max = Math.max(r, g, b);
180
+ const min = Math.min(r, g, b);
181
+ let h;
182
+ let s;
183
+ const v = max;
184
+
185
+ const d = max - min;
186
+ if (max === 0) {
187
+ s = 0;
188
+ } else {
189
+ s = d / max;
190
+ }
191
+
192
+ if (max === min) {
193
+ h = 0;
194
+ } else {
195
+ switch (max) {
196
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
197
+ case g: h = (b - r) / d + 2; break;
198
+ case b: h = (r - g) / d + 4; break;
199
+ }
200
+ h /= 6;
201
+ }
202
+ return { h: h * 360, s, v, a };
203
+ }
204
+
205
+ toARGB() {
206
+ return toHex([this.alpha * 255].concat(this.rgb));
207
+ }
208
+
209
+ compare(x) {
210
+ return (x.rgb &&
211
+ x.rgb[0] === this.rgb[0] &&
212
+ x.rgb[1] === this.rgb[1] &&
213
+ x.rgb[2] === this.rgb[2] &&
214
+ x.alpha === this.alpha) ? 0 : undefined;
215
+ }
216
+ }
217
+
218
+ Color.prototype.type = 'Color';
219
+
220
+ function clamp(v, max) {
221
+ return Math.min(Math.max(v, 0), max);
222
+ }
223
+
224
+ function toHex(v) {
225
+ return `#${v.map(c => {
226
+ c = clamp(Math.round(c), 255);
227
+ return (c < 16 ? '0' : '') + c.toString(16);
228
+ }).join('')}`;
229
+ }
230
+
231
+ Color.fromKeyword = keyword => {
232
+ let c;
233
+ const key = keyword.toLowerCase();
234
+ if (colors.hasOwnProperty(key)) {
235
+ c = new Color(colors[key].slice(1));
236
+ }
237
+ else if (key === 'transparent') {
238
+ c = new Color([0, 0, 0], 0);
239
+ }
240
+
241
+ if (c) {
242
+ c.value = keyword;
243
+ return c;
244
+ }
245
+ };
246
+ export default Color;
@@ -0,0 +1,29 @@
1
+ import Node from './node';
2
+ const _noSpaceCombinators = {
3
+ '': true,
4
+ ' ': true,
5
+ '|': true
6
+ };
7
+
8
+ class Combinator extends Node {
9
+ constructor(value) {
10
+ super();
11
+
12
+ if (value === ' ') {
13
+ this.value = ' ';
14
+ this.emptyOrWhitespace = true;
15
+ } else {
16
+ this.value = value ? value.trim() : '';
17
+ this.emptyOrWhitespace = this.value === '';
18
+ }
19
+ }
20
+
21
+ genCSS(context, output) {
22
+ const spaceOrEmpty = (context.compress || _noSpaceCombinators[this.value]) ? '' : ' ';
23
+ output.add(spaceOrEmpty + this.value + spaceOrEmpty);
24
+ }
25
+ }
26
+
27
+ Combinator.prototype.type = 'Combinator';
28
+
29
+ export default Combinator;
@@ -0,0 +1,29 @@
1
+ import Node from './node';
2
+ import getDebugInfo from './debug-info';
3
+
4
+ class Comment extends Node {
5
+ constructor(value, isLineComment, index, currentFileInfo) {
6
+ super();
7
+
8
+ this.value = value;
9
+ this.isLineComment = isLineComment;
10
+ this._index = index;
11
+ this._fileInfo = currentFileInfo;
12
+ this.allowRoot = true;
13
+ }
14
+
15
+ genCSS(context, output) {
16
+ if (this.debugInfo) {
17
+ output.add(getDebugInfo(context, this), this.fileInfo(), this.getIndex());
18
+ }
19
+ output.add(this.value);
20
+ }
21
+
22
+ isSilent(context) {
23
+ const isCompressed = context.compress && this.value[2] !== '!';
24
+ return this.isLineComment || isCompressed;
25
+ }
26
+ }
27
+
28
+ Comment.prototype.type = 'Comment';
29
+ export default Comment;
@@ -0,0 +1,43 @@
1
+ import Node from './node';
2
+
3
+ class Condition extends Node {
4
+ constructor(op, l, r, i, negate) {
5
+ super();
6
+
7
+ this.op = op.trim();
8
+ this.lvalue = l;
9
+ this.rvalue = r;
10
+ this._index = i;
11
+ this.negate = negate;
12
+ }
13
+
14
+ accept(visitor) {
15
+ this.lvalue = visitor.visit(this.lvalue);
16
+ this.rvalue = visitor.visit(this.rvalue);
17
+ }
18
+
19
+ eval(context) {
20
+ const result = ((op, a, b) => {
21
+ switch (op) {
22
+ case 'and': return a && b;
23
+ case 'or': return a || b;
24
+ default:
25
+ switch (Node.compare(a, b)) {
26
+ case -1:
27
+ return op === '<' || op === '=<' || op === '<=';
28
+ case 0:
29
+ return op === '=' || op === '>=' || op === '=<' || op === '<=';
30
+ case 1:
31
+ return op === '>' || op === '>=';
32
+ default:
33
+ return false;
34
+ }
35
+ }
36
+ })(this.op, this.lvalue.eval(context), this.rvalue.eval(context));
37
+
38
+ return this.negate ? !result : result;
39
+ }
40
+ }
41
+
42
+ Condition.prototype.type = 'Condition';
43
+ export default Condition;
@@ -0,0 +1,34 @@
1
+ const debugInfo = (context, ctx, lineSeparator) => {
2
+ let result = '';
3
+ if (context.dumpLineNumbers && !context.compress) {
4
+ switch (context.dumpLineNumbers) {
5
+ case 'comments':
6
+ result = debugInfo.asComment(ctx);
7
+ break;
8
+ case 'mediaquery':
9
+ result = debugInfo.asMediaQuery(ctx);
10
+ break;
11
+ case 'all':
12
+ result = debugInfo.asComment(ctx) + (lineSeparator || '') + debugInfo.asMediaQuery(ctx);
13
+ break;
14
+ }
15
+ }
16
+ return result;
17
+ };
18
+
19
+ debugInfo.asComment = ctx => `/* line ${ctx.debugInfo.lineNumber}, ${ctx.debugInfo.fileName} */\n`;
20
+
21
+ debugInfo.asMediaQuery = ctx => {
22
+ let filenameWithProtocol = ctx.debugInfo.fileName;
23
+ if (!/^[a-z]+:\/\//i.test(filenameWithProtocol)) {
24
+ filenameWithProtocol = `file://${filenameWithProtocol}`;
25
+ }
26
+ return `@media -sass-debug-info{filename{font-family:${filenameWithProtocol.replace(/([.:\/\\])/g, a => {
27
+ if (a == '\\') {
28
+ a = '\/';
29
+ }
30
+ return `\\${a}`;
31
+ })}}line{font-family:\\00003${ctx.debugInfo.lineNumber}}}\n`;
32
+ };
33
+
34
+ export default debugInfo;