less 4.6.7 → 4.8.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/dist/less-node.cjs +296 -64
- package/dist/less.cjs +271 -58
- package/dist/less.js +271 -58
- package/dist/less.min.js +2 -2
- package/dist/less.min.js.map +1 -1
- package/lib/less/deprecation.js +17 -2
- package/lib/less/parser/parser-input.js +21 -1
- package/lib/less/parser/parser.js +210 -29
- package/lib/less/tree/mixin-definition.js +30 -18
- package/lib/less/tree/nested-at-rule.js +6 -6
- package/lib/less-node/environment.js +3 -3
- package/lib/less-node/image-size.js +25 -6
- package/package.json +2 -2
package/dist/less.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Less - Leaner CSS v4.
|
|
2
|
+
* Less - Leaner CSS v4.8.0
|
|
3
3
|
* http://lesscss.org
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) 2009-2026, Alexis Sellier <self@cloudhead.net>
|
|
@@ -4100,12 +4100,23 @@
|
|
|
4100
4100
|
/**
|
|
4101
4101
|
* Permissive parsing. Ignores everything except matching {} [] () and quotes
|
|
4102
4102
|
* until matching token (outside of blocks)
|
|
4103
|
-
|
|
4104
|
-
|
|
4103
|
+
*
|
|
4104
|
+
* @param {string|RegExp} tok - stop token
|
|
4105
|
+
* @param {boolean} [detectBareVar] - when set, also record the position of the
|
|
4106
|
+
* first bare `@variable` reference (not `@{interpolation}`) that appears at
|
|
4107
|
+
* PAREN depth 0 — i.e. a structural reference, not a declaration value inside
|
|
4108
|
+
* `(...)`. Reuses this single pass (which already skips strings/comments) so
|
|
4109
|
+
* callers don't re-scan the text. Exposed as `.bareVarIndex` on the returned
|
|
4110
|
+
* group array (or null). `[...]`/`{...}` do NOT shield a reference — only
|
|
4111
|
+
* `(...)` (a declaration-value group) does.
|
|
4112
|
+
*/
|
|
4113
|
+
parserInput.$parseUntil = (tok, detectBareVar) => {
|
|
4105
4114
|
let quote = '';
|
|
4106
4115
|
let returnVal = null;
|
|
4107
4116
|
let inComment = false;
|
|
4108
4117
|
let blockDepth = 0;
|
|
4118
|
+
let parenDepth = 0;
|
|
4119
|
+
let bareVarIndex = null;
|
|
4109
4120
|
const blockStack = [];
|
|
4110
4121
|
const parseGroups = [];
|
|
4111
4122
|
const length = input.length;
|
|
@@ -4145,6 +4156,12 @@
|
|
|
4145
4156
|
i++;
|
|
4146
4157
|
continue;
|
|
4147
4158
|
}
|
|
4159
|
+
if (detectBareVar && bareVarIndex === null && nextChar === '@' && parenDepth === 0) {
|
|
4160
|
+
// A bare `@ident` (not `@{interpolation}`) outside any `(...)` —
|
|
4161
|
+
// a structural reference. Strings/comments are already skipped above.
|
|
4162
|
+
const after = input.charAt(i + 1);
|
|
4163
|
+
if (after && /[-\w]/.test(after)) { bareVarIndex = i; }
|
|
4164
|
+
}
|
|
4148
4165
|
switch (nextChar) {
|
|
4149
4166
|
case '\\':
|
|
4150
4167
|
i++;
|
|
@@ -4180,6 +4197,7 @@
|
|
|
4180
4197
|
case '(':
|
|
4181
4198
|
blockStack.push(')');
|
|
4182
4199
|
blockDepth++;
|
|
4200
|
+
parenDepth++;
|
|
4183
4201
|
break;
|
|
4184
4202
|
case '[':
|
|
4185
4203
|
blockStack.push(']');
|
|
@@ -4191,6 +4209,7 @@
|
|
|
4191
4209
|
const expected = blockStack.pop();
|
|
4192
4210
|
if (nextChar === expected) {
|
|
4193
4211
|
blockDepth--;
|
|
4212
|
+
if (nextChar === ')' && parenDepth > 0) { parenDepth--; }
|
|
4194
4213
|
} else {
|
|
4195
4214
|
// move the parser to the error and return expected
|
|
4196
4215
|
skipWhitespace(i - startPos);
|
|
@@ -4206,6 +4225,7 @@
|
|
|
4206
4225
|
}
|
|
4207
4226
|
} while (loop);
|
|
4208
4227
|
|
|
4228
|
+
if (Array.isArray(returnVal)) { returnVal.bareVarIndex = bareVarIndex; }
|
|
4209
4229
|
return returnVal ? returnVal : null;
|
|
4210
4230
|
};
|
|
4211
4231
|
|
|
@@ -4406,6 +4426,10 @@
|
|
|
4406
4426
|
|
|
4407
4427
|
const deprecationHandler = new DeprecationHandler();
|
|
4408
4428
|
|
|
4429
|
+
// Tracks `${deprecationId}@${index}` pairs already warned about, so a source
|
|
4430
|
+
// position that gets re-parsed via parser backtracking only warns once.
|
|
4431
|
+
const warnedDeprecations = new Set();
|
|
4432
|
+
|
|
4409
4433
|
/**
|
|
4410
4434
|
* @param {string} msg
|
|
4411
4435
|
* @param {number} index
|
|
@@ -4415,6 +4439,11 @@
|
|
|
4415
4439
|
function warn(msg, index, type, deprecationId) {
|
|
4416
4440
|
if (context.quiet) { return; }
|
|
4417
4441
|
if (deprecationId && context.quietDeprecations) { return; }
|
|
4442
|
+
if (deprecationId) {
|
|
4443
|
+
const key = `${deprecationId}@${index ?? parserInput.i}`;
|
|
4444
|
+
if (warnedDeprecations.has(key)) { return; }
|
|
4445
|
+
warnedDeprecations.add(key);
|
|
4446
|
+
}
|
|
4418
4447
|
if (deprecationId && !deprecationHandler.shouldWarn(deprecationId)) { return; }
|
|
4419
4448
|
|
|
4420
4449
|
logger$1.warn(
|
|
@@ -4430,6 +4459,75 @@
|
|
|
4430
4459
|
);
|
|
4431
4460
|
}
|
|
4432
4461
|
|
|
4462
|
+
/**
|
|
4463
|
+
* Warn that a bare `@variable` reference is being used in a non-value
|
|
4464
|
+
* position (an at-rule prelude, name, or identifier), where it still
|
|
4465
|
+
* resolves today but is deprecated in favour of `@{variable}` interpolation.
|
|
4466
|
+
*
|
|
4467
|
+
* @param {number} index - source position of the bare reference
|
|
4468
|
+
*/
|
|
4469
|
+
function warnBareAtRuleVariable(index) {
|
|
4470
|
+
warn('A bare @variable in an at-rule prelude is deprecated. Use @{variable} interpolation instead.', index, 'DEPRECATED', 'variable-in-at-rule-prelude');
|
|
4471
|
+
}
|
|
4472
|
+
|
|
4473
|
+
/**
|
|
4474
|
+
* Numeric-leading variable names are a Less extension rather than valid CSS
|
|
4475
|
+
* identifier syntax. Keep accepting them through Less 4, but make the Less 5
|
|
4476
|
+
* migration visible at every actual variable reference or definition.
|
|
4477
|
+
*
|
|
4478
|
+
* @param {string} name - either an @-prefixed name or the name inside @{...}
|
|
4479
|
+
* @param {number} index - source position of the variable token
|
|
4480
|
+
*/
|
|
4481
|
+
function warnNumericVariableName(name, index) {
|
|
4482
|
+
if (/^(?:@@?)?[0-9]/.test(name)) {
|
|
4483
|
+
warn('Variable names beginning with a number are deprecated and will be removed in Less 5.x. Rename the variable to start with a valid identifier character.', index, 'DEPRECATED', 'numeric-variable-name');
|
|
4484
|
+
}
|
|
4485
|
+
}
|
|
4486
|
+
|
|
4487
|
+
/**
|
|
4488
|
+
* A lone '-' is not a CSS identifier. Less historically accepts it as a
|
|
4489
|
+
* variable name; retain that in Less 4 only and warn on definitions,
|
|
4490
|
+
* ordinary references, and interpolation references.
|
|
4491
|
+
*
|
|
4492
|
+
* @param {string} name - either @-/@@-, or the name inside @{...}
|
|
4493
|
+
* @param {number} index - source position of the variable token
|
|
4494
|
+
*/
|
|
4495
|
+
function warnDashOnlyVariableName(name, index) {
|
|
4496
|
+
const bareName = name.replace(/^@@?/, '');
|
|
4497
|
+
if (bareName === '-') {
|
|
4498
|
+
warn('The dash-only variable names @- and @{-} are deprecated and will be removed in Less 5.x. Rename the variable to use a valid identifier.', index, 'DEPRECATED', 'dash-only-variable-name');
|
|
4499
|
+
}
|
|
4500
|
+
}
|
|
4501
|
+
|
|
4502
|
+
/**
|
|
4503
|
+
* A lone '-' is not a CSS identifier. Less historically accepts it as a mixin
|
|
4504
|
+
* name after '.' or '#'; retain that in Less 4 only.
|
|
4505
|
+
*
|
|
4506
|
+
* @param {string} name
|
|
4507
|
+
* @param {number} index
|
|
4508
|
+
*/
|
|
4509
|
+
function warnDashOnlyMixinName(name, index) {
|
|
4510
|
+
if (name === '.-' || name === '#-') {
|
|
4511
|
+
warn('The dash-only mixin names .-() and #-() are deprecated and will be removed in Less 5.x. Rename the mixin to use a valid CSS identifier.', index, 'DEPRECATED', 'dash-only-mixin-name');
|
|
4512
|
+
}
|
|
4513
|
+
}
|
|
4514
|
+
|
|
4515
|
+
/**
|
|
4516
|
+
* CSS @charset is a source-header declaration, not a general dynamic at-rule.
|
|
4517
|
+
* Less 4 keeps its historical interpolation behavior for compatibility, but
|
|
4518
|
+
* makes each dynamic spelling visible before Less 5 rejects it.
|
|
4519
|
+
*
|
|
4520
|
+
* @param {import('../tree/node.js').default} value
|
|
4521
|
+
* @param {number} index - source position of the @charset token
|
|
4522
|
+
*/
|
|
4523
|
+
function warnDynamicCharset(value, index) {
|
|
4524
|
+
if (value instanceof tree.Variable ||
|
|
4525
|
+
(value instanceof tree.Quoted &&
|
|
4526
|
+
(value.containsVariables() || value.value.match(value.propRegex)))) {
|
|
4527
|
+
warn('Dynamic @charset interpolation is deprecated and will be removed in Less 5.x. Use a static quoted encoding declaration instead.', index, 'DEPRECATED', 'dynamic-charset');
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
|
|
4433
4531
|
function expect(arg, msg) {
|
|
4434
4532
|
// some older browsers return typeof 'function' for RegExp
|
|
4435
4533
|
const result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
|
|
@@ -4883,7 +4981,7 @@
|
|
|
4883
4981
|
}
|
|
4884
4982
|
|
|
4885
4983
|
function condition() {
|
|
4886
|
-
return [expect(parsers.condition, 'expected condition')];
|
|
4984
|
+
return [expect(() => parsers.condition(false, true), 'expected condition')];
|
|
4887
4985
|
}
|
|
4888
4986
|
},
|
|
4889
4987
|
|
|
@@ -5008,6 +5106,8 @@
|
|
|
5008
5106
|
|
|
5009
5107
|
parserInput.save();
|
|
5010
5108
|
if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^@@?[\w-]+/))) {
|
|
5109
|
+
warnNumericVariableName(name, index);
|
|
5110
|
+
warnDashOnlyVariableName(name, index);
|
|
5011
5111
|
ch = parserInput.currentChar();
|
|
5012
5112
|
if ((ch === '(' && !parserInput.prevChar().match(/^\s/))
|
|
5013
5113
|
|| (ch === '[' && !parserInput.prevChar().match(/^\s/))) {
|
|
@@ -5030,6 +5130,8 @@
|
|
|
5030
5130
|
const index = parserInput.i;
|
|
5031
5131
|
|
|
5032
5132
|
if (parserInput.currentChar() === '@' && (curly = parserInput.$re(/^@\{([\w-]+)\}/))) {
|
|
5133
|
+
warnNumericVariableName(curly[1], index);
|
|
5134
|
+
warnDashOnlyVariableName(curly[1], index);
|
|
5033
5135
|
return new(tree.Variable)(`@${curly[1]}`, index + currentIndex, fileInfo);
|
|
5034
5136
|
}
|
|
5035
5137
|
},
|
|
@@ -5152,7 +5254,11 @@
|
|
|
5152
5254
|
variable: function () {
|
|
5153
5255
|
let name;
|
|
5154
5256
|
|
|
5155
|
-
if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*:/))) {
|
|
5257
|
+
if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*:/))) {
|
|
5258
|
+
warnNumericVariableName(name[1], parserInput.i - name[0].length);
|
|
5259
|
+
warnDashOnlyVariableName(name[1], parserInput.i - name[0].length);
|
|
5260
|
+
return name[1];
|
|
5261
|
+
}
|
|
5156
5262
|
},
|
|
5157
5263
|
|
|
5158
5264
|
//
|
|
@@ -5182,6 +5288,8 @@
|
|
|
5182
5288
|
}
|
|
5183
5289
|
|
|
5184
5290
|
if (!inValue) {
|
|
5291
|
+
warnNumericVariableName(name[1], i);
|
|
5292
|
+
warnDashOnlyVariableName(name[1], i);
|
|
5185
5293
|
name = name[1];
|
|
5186
5294
|
}
|
|
5187
5295
|
|
|
@@ -5338,6 +5446,9 @@
|
|
|
5338
5446
|
if (inValue || parsers.end()) {
|
|
5339
5447
|
parserInput.forget();
|
|
5340
5448
|
const mixin = new(tree.mixin.Call)(elements, args, index + currentIndex, fileInfo, !lookups && important);
|
|
5449
|
+
for (const element of elements) {
|
|
5450
|
+
warnDashOnlyMixinName(element.value, element._index - currentIndex);
|
|
5451
|
+
}
|
|
5341
5452
|
if (lookups) {
|
|
5342
5453
|
return new tree.NamespaceValue(mixin, lookups);
|
|
5343
5454
|
}
|
|
@@ -5534,6 +5645,7 @@
|
|
|
5534
5645
|
let ruleset;
|
|
5535
5646
|
let cond;
|
|
5536
5647
|
let variadic = false;
|
|
5648
|
+
const index = parserInput.i;
|
|
5537
5649
|
if ((parserInput.currentChar() !== '.' && parserInput.currentChar() !== '#') ||
|
|
5538
5650
|
parserInput.peek(/^[^{]*\}/)) {
|
|
5539
5651
|
return;
|
|
@@ -5569,6 +5681,7 @@
|
|
|
5569
5681
|
|
|
5570
5682
|
if (ruleset) {
|
|
5571
5683
|
parserInput.forget();
|
|
5684
|
+
warnDashOnlyMixinName(name, index);
|
|
5572
5685
|
return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
|
|
5573
5686
|
} else {
|
|
5574
5687
|
parserInput.restore();
|
|
@@ -5980,7 +6093,7 @@
|
|
|
5980
6093
|
if (parserInput.$char(';')) {
|
|
5981
6094
|
value = new Anonymous('');
|
|
5982
6095
|
} else {
|
|
5983
|
-
value = this.permissiveValue(/[;}]
|
|
6096
|
+
value = this.permissiveValue(/[;}]/);
|
|
5984
6097
|
}
|
|
5985
6098
|
}
|
|
5986
6099
|
// Try to store values as anonymous
|
|
@@ -6039,8 +6152,12 @@
|
|
|
6039
6152
|
* math is allowed.
|
|
6040
6153
|
*
|
|
6041
6154
|
* @param {RexExp} untilTokens - Characters to stop parsing at
|
|
6155
|
+
* @param {boolean} [deprecateVariables] - when set, this is an at-rule
|
|
6156
|
+
* prelude (non-value position); accept `@{var}` interpolation and warn
|
|
6157
|
+
* on a bare `@var` reference (which resolves today but is deprecated).
|
|
6042
6158
|
*/
|
|
6043
|
-
permissiveValue: function (untilTokens) {
|
|
6159
|
+
permissiveValue: function (untilTokens, deprecateVariables) {
|
|
6160
|
+
const entities = this.entities;
|
|
6044
6161
|
let i;
|
|
6045
6162
|
let e;
|
|
6046
6163
|
let done;
|
|
@@ -6067,7 +6184,20 @@
|
|
|
6067
6184
|
value.push(e);
|
|
6068
6185
|
continue;
|
|
6069
6186
|
}
|
|
6070
|
-
|
|
6187
|
+
if (deprecateVariables) {
|
|
6188
|
+
// In an at-rule prelude, `@{var}` interpolation is the supported
|
|
6189
|
+
// form; consume it here so its `{` is not mistaken for a block.
|
|
6190
|
+
e = entities.variableCurly();
|
|
6191
|
+
if (!e) {
|
|
6192
|
+
const varIndex = parserInput.i;
|
|
6193
|
+
e = this.entity();
|
|
6194
|
+
if (e && e.type === 'Variable') {
|
|
6195
|
+
warnBareAtRuleVariable(varIndex);
|
|
6196
|
+
}
|
|
6197
|
+
}
|
|
6198
|
+
} else {
|
|
6199
|
+
e = this.entity();
|
|
6200
|
+
}
|
|
6071
6201
|
if (e) {
|
|
6072
6202
|
value.push(e);
|
|
6073
6203
|
}
|
|
@@ -6094,7 +6224,7 @@
|
|
|
6094
6224
|
}
|
|
6095
6225
|
parserInput.save();
|
|
6096
6226
|
|
|
6097
|
-
value = parserInput.$parseUntil(tok);
|
|
6227
|
+
value = parserInput.$parseUntil(tok, deprecateVariables);
|
|
6098
6228
|
|
|
6099
6229
|
if (value) {
|
|
6100
6230
|
if (typeof value === 'string') {
|
|
@@ -6104,6 +6234,14 @@
|
|
|
6104
6234
|
parserInput.forget();
|
|
6105
6235
|
return new tree.Anonymous('', index);
|
|
6106
6236
|
}
|
|
6237
|
+
// At-rule prelude: `$parseUntil` (deprecateVariables) records the
|
|
6238
|
+
// first bare `@var` it saw outside any `(...)` in its single pass —
|
|
6239
|
+
// a structural reference (`[...]`/`{...}` don't shield it, only a
|
|
6240
|
+
// declaration-value `(...)` does). Warn once here rather than
|
|
6241
|
+
// re-scanning the text.
|
|
6242
|
+
if (deprecateVariables && value.bareVarIndex !== null && value.bareVarIndex !== undefined) {
|
|
6243
|
+
warnBareAtRuleVariable(value.bareVarIndex);
|
|
6244
|
+
}
|
|
6107
6245
|
/** @type {string} */
|
|
6108
6246
|
let item;
|
|
6109
6247
|
for (i = 0; i < value.length; i++) {
|
|
@@ -6120,11 +6258,14 @@
|
|
|
6120
6258
|
const quote = new tree.Quoted('\'', item, true, index, fileInfo);
|
|
6121
6259
|
const variableRegex = /@([\w-]+)/g;
|
|
6122
6260
|
const propRegex = /\$([\w-]+)/g;
|
|
6123
|
-
|
|
6124
|
-
|
|
6261
|
+
// At-rule preludes are handled once above via
|
|
6262
|
+
// `value.bareVarIndex`; the `variable-in-unknown-value`
|
|
6263
|
+
// notice is for unknown declaration values only.
|
|
6264
|
+
if (!deprecateVariables && variableRegex.test(item)) {
|
|
6265
|
+
warn('@variable in unknown values will not be evaluated as variables in the future. Use @{variable}', index, 'DEPRECATED', 'variable-in-unknown-value');
|
|
6125
6266
|
}
|
|
6126
6267
|
if (propRegex.test(item)) {
|
|
6127
|
-
warn('$
|
|
6268
|
+
warn('$property in unknown values will not be evaluated as property references in the future. Use ${property}', index, 'DEPRECATED', 'property-in-unknown-value');
|
|
6128
6269
|
}
|
|
6129
6270
|
quote.variableRegex = /@([\w-]+)|@{([\w-]+)}/g;
|
|
6130
6271
|
quote.propRegex = /\$([\w-]+)|\${([\w-]+)}/g;
|
|
@@ -6233,7 +6374,17 @@
|
|
|
6233
6374
|
}
|
|
6234
6375
|
parserInput.restore();
|
|
6235
6376
|
|
|
6236
|
-
e = entities.declarationCall.bind(this)() || cssKeyword() || entities.keyword() || entities.
|
|
6377
|
+
e = entities.declarationCall.bind(this)() || cssKeyword() || entities.keyword() || entities.variableCurly();
|
|
6378
|
+
if (!e) {
|
|
6379
|
+
const varIndex = parserInput.i;
|
|
6380
|
+
const bareVariable = entities.variable();
|
|
6381
|
+
if (bareVariable) {
|
|
6382
|
+
warnBareAtRuleVariable(varIndex);
|
|
6383
|
+
e = bareVariable;
|
|
6384
|
+
} else {
|
|
6385
|
+
e = entities.mixinLookup();
|
|
6386
|
+
}
|
|
6387
|
+
}
|
|
6237
6388
|
if (e) {
|
|
6238
6389
|
nodes.push(e);
|
|
6239
6390
|
if (e.type === 'Variable' ||
|
|
@@ -6244,7 +6395,7 @@
|
|
|
6244
6395
|
let closed = false;
|
|
6245
6396
|
p = this.property();
|
|
6246
6397
|
parserInput.save();
|
|
6247
|
-
if (!p && syntaxOptions.queryInParens && parserInput.$re(/^[
|
|
6398
|
+
if (!p && syntaxOptions.queryInParens && parserInput.$re(/^(?:[^()]|\([^()]*\))*\s*([<>]=|<=|>=|[<>]|=)/)) {
|
|
6248
6399
|
parserInput.restore();
|
|
6249
6400
|
p = this.condition();
|
|
6250
6401
|
|
|
@@ -6324,7 +6475,17 @@
|
|
|
6324
6475
|
features[features.length - 1].noSpacing = false;
|
|
6325
6476
|
}
|
|
6326
6477
|
} else {
|
|
6327
|
-
e = entities.
|
|
6478
|
+
e = entities.variableCurly();
|
|
6479
|
+
if (!e) {
|
|
6480
|
+
const varIndex = parserInput.i;
|
|
6481
|
+
const bareVariable = entities.variable();
|
|
6482
|
+
if (bareVariable) {
|
|
6483
|
+
warnBareAtRuleVariable(varIndex);
|
|
6484
|
+
e = bareVariable;
|
|
6485
|
+
} else {
|
|
6486
|
+
e = entities.mixinLookup();
|
|
6487
|
+
}
|
|
6488
|
+
}
|
|
6328
6489
|
if (e) {
|
|
6329
6490
|
features.push(e);
|
|
6330
6491
|
if (!parserInput.$char(',')) { break; }
|
|
@@ -6438,8 +6599,24 @@
|
|
|
6438
6599
|
return null;
|
|
6439
6600
|
}
|
|
6440
6601
|
},
|
|
6602
|
+
/**
|
|
6603
|
+
* An entity in a non-value at-rule position (an at-rule identifier,
|
|
6604
|
+
* name, or keyword-list item — e.g. the name in `@keyframes @foo`).
|
|
6605
|
+
* `@{foo}` interpolation is the supported form; a bare `@foo` still
|
|
6606
|
+
* resolves but is deprecated.
|
|
6607
|
+
*/
|
|
6608
|
+
atRuleEntity: function () {
|
|
6609
|
+
const curly = this.entities.variableCurly();
|
|
6610
|
+
if (curly) { return curly; }
|
|
6611
|
+
const index = parserInput.i;
|
|
6612
|
+
const e = this.entity();
|
|
6613
|
+
if (e && e.type === 'Variable') {
|
|
6614
|
+
warnBareAtRuleVariable(index);
|
|
6615
|
+
}
|
|
6616
|
+
return e;
|
|
6617
|
+
},
|
|
6441
6618
|
atruleUnknown: function (value, name, hasBlock) {
|
|
6442
|
-
value = this.permissiveValue(/^[{;]
|
|
6619
|
+
value = this.permissiveValue(/^[{;]/, true);
|
|
6443
6620
|
hasBlock = (parserInput.currentChar() === '{');
|
|
6444
6621
|
if (!value) {
|
|
6445
6622
|
if (!hasBlock && parserInput.currentChar() !== ';') {
|
|
@@ -6455,16 +6632,16 @@
|
|
|
6455
6632
|
rules = this.blockRuleset();
|
|
6456
6633
|
parserInput.save();
|
|
6457
6634
|
if (!rules && !isRooted) {
|
|
6458
|
-
value = this.
|
|
6635
|
+
value = this.atRuleEntity();
|
|
6459
6636
|
rules = this.blockRuleset();
|
|
6460
6637
|
}
|
|
6461
6638
|
if (!rules && !isRooted) {
|
|
6462
6639
|
parserInput.restore();
|
|
6463
6640
|
var e = [];
|
|
6464
|
-
value = this.
|
|
6641
|
+
value = this.atRuleEntity();
|
|
6465
6642
|
while (parserInput.$char(',')) {
|
|
6466
6643
|
e.push(value);
|
|
6467
|
-
value = this.
|
|
6644
|
+
value = this.atRuleEntity();
|
|
6468
6645
|
}
|
|
6469
6646
|
if (value && e.length > 0) {
|
|
6470
6647
|
e.push(value);
|
|
@@ -6549,12 +6726,28 @@
|
|
|
6549
6726
|
parserInput.commentStore.length = 0;
|
|
6550
6727
|
|
|
6551
6728
|
if (hasIdentifier) {
|
|
6552
|
-
value = this.
|
|
6729
|
+
value = this.atRuleEntity();
|
|
6553
6730
|
if (!value) {
|
|
6554
6731
|
error(`expected ${name} identifier`);
|
|
6555
6732
|
}
|
|
6733
|
+
if (nonVendorSpecificName === '@charset') {
|
|
6734
|
+
warnDynamicCharset(value, index);
|
|
6735
|
+
}
|
|
6556
6736
|
} else if (hasExpression) {
|
|
6737
|
+
// `@namespace` may carry an interpolated `@{ns}` prefix (or a
|
|
6738
|
+
// deprecated bare `@ns`). Parse that prefix directly so `@{ns}`
|
|
6739
|
+
// is accepted here without treating value positions as
|
|
6740
|
+
// interpolation contexts, then read the namespace URL.
|
|
6741
|
+
let prefix = this.entities.variableCurly();
|
|
6742
|
+
if (!prefix && parserInput.peek(/^@@?[\w-]/)) {
|
|
6743
|
+
const prefixIndex = parserInput.i;
|
|
6744
|
+
prefix = this.entities.variable();
|
|
6745
|
+
if (prefix) { warnBareAtRuleVariable(prefixIndex); }
|
|
6746
|
+
}
|
|
6557
6747
|
value = this.expression();
|
|
6748
|
+
if (prefix) {
|
|
6749
|
+
value = value ? new(tree.Expression)([prefix, ...value.value]) : prefix;
|
|
6750
|
+
}
|
|
6558
6751
|
if (!value) {
|
|
6559
6752
|
error(`expected ${name} expression`);
|
|
6560
6753
|
}
|
|
@@ -6744,7 +6937,7 @@
|
|
|
6744
6937
|
return condition || a;
|
|
6745
6938
|
}
|
|
6746
6939
|
},
|
|
6747
|
-
condition: function (needsParens) {
|
|
6940
|
+
condition: function (needsParens, allowConditionOperands) {
|
|
6748
6941
|
let result;
|
|
6749
6942
|
let logical;
|
|
6750
6943
|
let next;
|
|
@@ -6752,13 +6945,13 @@
|
|
|
6752
6945
|
return parserInput.$str('or');
|
|
6753
6946
|
}
|
|
6754
6947
|
|
|
6755
|
-
result = this.conditionAnd(needsParens);
|
|
6948
|
+
result = this.conditionAnd(needsParens, allowConditionOperands);
|
|
6756
6949
|
if (!result) {
|
|
6757
6950
|
return ;
|
|
6758
6951
|
}
|
|
6759
6952
|
logical = or();
|
|
6760
6953
|
if (logical) {
|
|
6761
|
-
next = this.condition(needsParens);
|
|
6954
|
+
next = this.condition(needsParens, allowConditionOperands);
|
|
6762
6955
|
if (next) {
|
|
6763
6956
|
result = new(tree.Condition)(logical, result, next);
|
|
6764
6957
|
} else {
|
|
@@ -6767,13 +6960,13 @@
|
|
|
6767
6960
|
}
|
|
6768
6961
|
return result;
|
|
6769
6962
|
},
|
|
6770
|
-
conditionAnd: function (needsParens) {
|
|
6963
|
+
conditionAnd: function (needsParens, allowConditionOperands) {
|
|
6771
6964
|
let result;
|
|
6772
6965
|
let logical;
|
|
6773
6966
|
let next;
|
|
6774
6967
|
const self = this;
|
|
6775
6968
|
function insideCondition() {
|
|
6776
|
-
const cond = self.negatedCondition(needsParens) || self.parenthesisCondition(needsParens);
|
|
6969
|
+
const cond = self.negatedCondition(needsParens, allowConditionOperands) || self.parenthesisCondition(needsParens, allowConditionOperands);
|
|
6777
6970
|
if (!cond && !needsParens) {
|
|
6778
6971
|
return self.atomicCondition(needsParens);
|
|
6779
6972
|
}
|
|
@@ -6787,9 +6980,12 @@
|
|
|
6787
6980
|
if (!result) {
|
|
6788
6981
|
return ;
|
|
6789
6982
|
}
|
|
6983
|
+
if (allowConditionOperands) {
|
|
6984
|
+
result = this.atomicCondition(needsParens, result, allowConditionOperands) || result;
|
|
6985
|
+
}
|
|
6790
6986
|
logical = and();
|
|
6791
6987
|
if (logical) {
|
|
6792
|
-
next = this.conditionAnd(needsParens);
|
|
6988
|
+
next = this.conditionAnd(needsParens, allowConditionOperands);
|
|
6793
6989
|
if (next) {
|
|
6794
6990
|
result = new(tree.Condition)(logical, result, next);
|
|
6795
6991
|
} else {
|
|
@@ -6798,9 +6994,9 @@
|
|
|
6798
6994
|
}
|
|
6799
6995
|
return result;
|
|
6800
6996
|
},
|
|
6801
|
-
negatedCondition: function (needsParens) {
|
|
6997
|
+
negatedCondition: function (needsParens, allowConditionOperands) {
|
|
6802
6998
|
if (parserInput.$str('not')) {
|
|
6803
|
-
const result = this.parenthesisCondition(needsParens);
|
|
6999
|
+
const result = this.parenthesisCondition(needsParens, allowConditionOperands);
|
|
6804
7000
|
if (result) {
|
|
6805
7001
|
result.negate = !result.negate;
|
|
6806
7002
|
return result;
|
|
@@ -6817,11 +7013,11 @@
|
|
|
6817
7013
|
}
|
|
6818
7014
|
}
|
|
6819
7015
|
},
|
|
6820
|
-
parenthesisCondition: function (needsParens) {
|
|
7016
|
+
parenthesisCondition: function (needsParens, allowConditionOperands) {
|
|
6821
7017
|
function tryConditionFollowedByParenthesis(me) {
|
|
6822
7018
|
let body;
|
|
6823
7019
|
parserInput.save();
|
|
6824
|
-
body = me.condition(needsParens);
|
|
7020
|
+
body = me.condition(needsParens, allowConditionOperands);
|
|
6825
7021
|
if (!body) {
|
|
6826
7022
|
parserInput.restore();
|
|
6827
7023
|
return ;
|
|
@@ -6858,7 +7054,7 @@
|
|
|
6858
7054
|
parserInput.forget();
|
|
6859
7055
|
return body;
|
|
6860
7056
|
},
|
|
6861
|
-
atomicCondition: function (needsParens, preparsedCond) {
|
|
7057
|
+
atomicCondition: function (needsParens, preparsedCond, allowConditionOperands) {
|
|
6862
7058
|
const entities = this.entities;
|
|
6863
7059
|
const index = parserInput.i;
|
|
6864
7060
|
let a;
|
|
@@ -6867,7 +7063,7 @@
|
|
|
6867
7063
|
let op;
|
|
6868
7064
|
|
|
6869
7065
|
const cond = (function() {
|
|
6870
|
-
return this.addition() || entities.keyword() || entities.quoted() || entities.mixinLookup();
|
|
7066
|
+
return (allowConditionOperands && this.parenthesisCondition(needsParens)) || this.addition() || entities.keyword() || entities.quoted() || entities.mixinLookup();
|
|
6871
7067
|
}).bind(this);
|
|
6872
7068
|
|
|
6873
7069
|
if (preparsedCond) {
|
|
@@ -7028,6 +7224,11 @@
|
|
|
7028
7224
|
}
|
|
7029
7225
|
for (k = 0; k < name.length; k++) {
|
|
7030
7226
|
s = name[k];
|
|
7227
|
+
if (s.charAt(0) === '@') {
|
|
7228
|
+
const variableName = s.slice(2, -1);
|
|
7229
|
+
warnNumericVariableName(variableName, index[k]);
|
|
7230
|
+
warnDashOnlyVariableName(variableName, index[k]);
|
|
7231
|
+
}
|
|
7031
7232
|
name[k] = (s.charAt(0) !== '@' && s.charAt(0) !== '$') ?
|
|
7032
7233
|
new(tree.Keyword)(s) :
|
|
7033
7234
|
(s.charAt(0) === '@' ?
|
|
@@ -8617,16 +8818,16 @@
|
|
|
8617
8818
|
self.features = new Value(self.permute(/** @type {Node[][]} */ (/** @type {unknown} */ (path))).map(
|
|
8618
8819
|
/** @param {Node | Node[]} path */
|
|
8619
8820
|
path => {
|
|
8620
|
-
|
|
8821
|
+
path = /** @type {Node[]} */ (path).map(
|
|
8621
8822
|
/** @param {Node & { toCSS?: Function }} fragment */
|
|
8622
|
-
|
|
8823
|
+
fragment => fragment.toCSS ? fragment : new Anonymous(/** @type {string} */ (/** @type {unknown} */ (fragment))));
|
|
8623
8824
|
|
|
8624
|
-
|
|
8825
|
+
for (i = /** @type {Node[]} */ (path).length - 1; i > 0; i--) {
|
|
8625
8826
|
/** @type {Node[]} */ (path).splice(i, 0, new Anonymous('and'));
|
|
8626
|
-
|
|
8827
|
+
}
|
|
8627
8828
|
|
|
8628
|
-
|
|
8629
|
-
|
|
8829
|
+
return new Expression(/** @type {Node[]} */ (path));
|
|
8830
|
+
}));
|
|
8630
8831
|
self.setParent(self.features, self);
|
|
8631
8832
|
|
|
8632
8833
|
// Fake a tree-node that doesn't output anything.
|
|
@@ -10980,35 +11181,47 @@
|
|
|
10980
11181
|
*/
|
|
10981
11182
|
matchArgs(args, context) {
|
|
10982
11183
|
const allArgsCnt = (args && args.length) || 0;
|
|
10983
|
-
|
|
10984
|
-
const
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
}
|
|
10989
|
-
|
|
11184
|
+
const evaldArguments = new Array(this.params.length);
|
|
11185
|
+
const positionalArgs = [];
|
|
11186
|
+
let positionalIndex = 0;
|
|
11187
|
+
|
|
11188
|
+
for (let i = 0; i < allArgsCnt; i++) {
|
|
11189
|
+
const arg = /** @type {MixinArg[]} */ (args)[i];
|
|
11190
|
+
if (!arg.name) {
|
|
11191
|
+
positionalArgs.push(arg);
|
|
11192
|
+
continue;
|
|
10990
11193
|
}
|
|
10991
|
-
}, 0);
|
|
10992
11194
|
|
|
10993
|
-
|
|
10994
|
-
if (
|
|
11195
|
+
const paramIndex = this.params.findIndex((param, index) => param.name === arg.name && !evaldArguments[index]);
|
|
11196
|
+
if (paramIndex < 0) {
|
|
10995
11197
|
return false;
|
|
10996
11198
|
}
|
|
10997
|
-
|
|
10998
|
-
|
|
11199
|
+
evaldArguments[paramIndex] = arg;
|
|
11200
|
+
}
|
|
11201
|
+
|
|
11202
|
+
for (let i = 0; i < this.params.length; i++) {
|
|
11203
|
+
if (evaldArguments[i]) {
|
|
11204
|
+
continue;
|
|
10999
11205
|
}
|
|
11000
|
-
|
|
11001
|
-
|
|
11206
|
+
if (this.params[i].variadic) {
|
|
11207
|
+
positionalIndex = positionalArgs.length;
|
|
11208
|
+
continue;
|
|
11209
|
+
}
|
|
11210
|
+
if (positionalIndex < positionalArgs.length) {
|
|
11211
|
+
evaldArguments[i] = positionalArgs[positionalIndex++];
|
|
11212
|
+
} else if (!this.params[i].name || !this.params[i].value) {
|
|
11002
11213
|
return false;
|
|
11003
11214
|
}
|
|
11004
11215
|
}
|
|
11005
11216
|
|
|
11006
|
-
|
|
11007
|
-
|
|
11217
|
+
if (positionalIndex < positionalArgs.length) {
|
|
11218
|
+
return false;
|
|
11219
|
+
}
|
|
11008
11220
|
|
|
11009
|
-
|
|
11221
|
+
// check patterns
|
|
11222
|
+
for (let i = 0; i < this.arity; i++) {
|
|
11010
11223
|
if (!this.params[i].name && !this.params[i].variadic) {
|
|
11011
|
-
if (
|
|
11224
|
+
if (evaldArguments[i].value.eval(context).toCSS(/** @type {EvalContext} */ ({})) != /** @type {Node} */ (this.params[i].value).eval(context).toCSS(/** @type {EvalContext} */ ({}))) {
|
|
11012
11225
|
return false;
|
|
11013
11226
|
}
|
|
11014
11227
|
}
|
|
@@ -14175,7 +14388,7 @@
|
|
|
14175
14388
|
};
|
|
14176
14389
|
|
|
14177
14390
|
var name = "less";
|
|
14178
|
-
var version = "4.
|
|
14391
|
+
var version = "4.8.0";
|
|
14179
14392
|
var description = "Leaner CSS";
|
|
14180
14393
|
var homepage = "http://lesscss.org";
|
|
14181
14394
|
var author = {
|
|
@@ -14245,7 +14458,7 @@
|
|
|
14245
14458
|
var optionalDependencies = {
|
|
14246
14459
|
errno: "^0.1.1",
|
|
14247
14460
|
"graceful-fs": "^4.1.2",
|
|
14248
|
-
"image-size": "
|
|
14461
|
+
"probe-image-size": "^7.2.3",
|
|
14249
14462
|
"make-dir": "^5.1.0",
|
|
14250
14463
|
mime: "^1.4.1",
|
|
14251
14464
|
needle: "^3.1.0",
|