diff --git a/lib/ValuesParser.js b/lib/ValuesParser.js index 82d9e5a..5f65d6f 100644 --- a/lib/ValuesParser.js +++ b/lib/ValuesParser.js @@ -148,6 +148,8 @@ module.exports = class ValuesParser extends Parser { if (Punctuation.chars.includes(type)) { Punctuation.fromTokens(tokens, this); + } else if (type === 'word' && Operator.compact.test(value)) { + Operator.fromTokens(tokens, this); } else if (Func.test(tokens)) { Func.fromTokens(tokens, this); } else if (this.options.interpolation && Interpolation.test(tokens, this)) { diff --git a/lib/nodes/Operator.js b/lib/nodes/Operator.js index 2fac9af..aed491c 100644 --- a/lib/nodes/Operator.js +++ b/lib/nodes/Operator.js @@ -14,6 +14,7 @@ const Node = require('./Node'); const operators = ['+', '-', '/', '*', '%', '=', '<=', '>=', '<', '>']; const operRegex = new RegExp(`([/|*}])`); +const compactRegex = /^\*\b/; class Operator extends Node { constructor(options) { @@ -33,6 +34,10 @@ class Operator extends Node { return operRegex; } + static get compact() { + return compactRegex; + } + static tokenize(tokens, parser) { const [first, ...rest] = tokens; const [, value, startLine, , endLine, endChar] = first; diff --git a/test/fixtures/func.js b/test/fixtures/func.js index c58e3bf..7b4f6ea 100644 --- a/test/fixtures/func.js +++ b/test/fixtures/func.js @@ -29,6 +29,7 @@ module.exports = { 'lCH(40% 68.8 34.5 / 50%)', 'hwb(90deg 0% 0% / 0.5)', 'calc(-0.5 * var(foo))', + 'calc(var(--foo)*var(--bar))', 'calc(1px + -2vw - 4px)', 'calc(((768px - 100vw) / 2) - 15px)', 'bar(baz(black, 10%), 10%)', diff --git a/test/snapshots/func.test.js.md b/test/snapshots/func.test.js.md index 4591cb5..b91d405 100644 --- a/test/snapshots/func.test.js.md +++ b/test/snapshots/func.test.js.md @@ -5114,3 +5114,988 @@ Generated by [AVA](https://avajs.dev). [Symbol(isClean)]: false, }, ] + +## calc(-0.5*var(foo)) + +> Snapshot 1 + + 'calc(-0.5*var(foo))' + +> Snapshot 2 + + 'calc(-0.5*var(foo))' + +> Snapshot 3 + + [ + Func { + isColor: false, + isVar: false, + name: 'calc', + nodes: [ + Numeric { + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: '-0.5*var(foo)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'numeric', + unit: '', + value: '-0.5', + [Symbol(isClean)]: false, + }, + Operator { + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: '-0.5*var(foo)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'operator', + value: '*', + [Symbol(isClean)]: false, + }, + Func { + isColor: false, + isVar: false, + name: 'var', + nodes: [ + Word { + isColor: false, + isHex: false, + isUrl: false, + isVariable: false, + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: 'foo', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'word', + value: 'foo', + [Symbol(isClean)]: false, + }, + ], + params: '(foo)', + parent: [Circular], + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 9, + line: 1, + offset: 8, + }, + input: Input { + css: '-0.5*var(foo)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ], + params: '(-0.5*var(foo))', + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 19, + line: 1, + offset: 18, + }, + input: Input { + css: 'calc(-0.5*var(foo))', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ] + +## calc(var(--foo)) + +> Snapshot 1 + + 'calc(var(--foo))' + +> Snapshot 2 + + 'calc(var(--foo))' + +> Snapshot 3 + + [ + Func { + isColor: false, + isVar: false, + name: 'calc', + nodes: [ + Func { + isColor: false, + isVar: true, + name: 'var', + nodes: [ + Word { + isColor: false, + isHex: false, + isUrl: false, + isVariable: true, + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: '--foo', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'word', + value: '--foo', + [Symbol(isClean)]: false, + }, + ], + params: '(--foo)', + parent: [Circular], + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 4, + line: 1, + offset: 3, + }, + input: Input { + css: 'var(--foo)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ], + params: '(var(--foo))', + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 16, + line: 1, + offset: 15, + }, + input: Input { + css: 'calc(var(--foo))', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ] + +## calc(var(--foo) * var(--bar)) + +> Snapshot 1 + + 'calc(var(--foo) * var(--bar))' + +> Snapshot 2 + + 'calc(var(--foo) * var(--bar))' + +> Snapshot 3 + + [ + Func { + isColor: false, + isVar: false, + name: 'calc', + nodes: [ + Func { + isColor: false, + isVar: true, + name: 'var', + nodes: [ + Word { + isColor: false, + isHex: false, + isUrl: false, + isVariable: true, + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: '--foo', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'word', + value: '--foo', + [Symbol(isClean)]: false, + }, + ], + params: '(--foo)', + parent: [Circular], + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 4, + line: 1, + offset: 3, + }, + input: Input { + css: 'var(--foo) * var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + Operator { + parent: [Circular], + raws: { + after: '', + before: ' ', + }, + source: { + end: { + column: 12, + line: 1, + offset: 11, + }, + input: Input { + css: 'var(--foo) * var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 12, + line: 1, + offset: 11, + }, + }, + type: 'operator', + value: '*', + [Symbol(isClean)]: false, + }, + Func { + isColor: false, + isVar: true, + name: 'var', + nodes: [ + Word { + isColor: false, + isHex: false, + isUrl: false, + isVariable: true, + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: '--bar', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'word', + value: '--bar', + [Symbol(isClean)]: false, + }, + ], + params: '(--bar)', + parent: [Circular], + raws: { + after: '', + before: ' ', + semicolon: false, + }, + source: { + end: { + column: 17, + line: 1, + offset: 16, + }, + input: Input { + css: 'var(--foo) * var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 14, + line: 1, + offset: 13, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ], + params: '(var(--foo) * var(--bar))', + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 29, + line: 1, + offset: 28, + }, + input: Input { + css: 'calc(var(--foo) * var(--bar))', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ] + +## calc(var(--foo)* var(--bar)) + +> Snapshot 1 + + 'calc(var(--foo)* var(--bar))' + +> Snapshot 2 + + 'calc(var(--foo)* var(--bar))' + +> Snapshot 3 + + [ + Func { + isColor: false, + isVar: false, + name: 'calc', + nodes: [ + Func { + isColor: false, + isVar: true, + name: 'var', + nodes: [ + Word { + isColor: false, + isHex: false, + isUrl: false, + isVariable: true, + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: '--foo', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'word', + value: '--foo', + [Symbol(isClean)]: false, + }, + ], + params: '(--foo)', + parent: [Circular], + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 4, + line: 1, + offset: 3, + }, + input: Input { + css: 'var(--foo)* var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + Operator { + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 11, + line: 1, + offset: 10, + }, + input: Input { + css: 'var(--foo)* var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 11, + line: 1, + offset: 10, + }, + }, + type: 'operator', + value: '*', + [Symbol(isClean)]: false, + }, + Func { + isColor: false, + isVar: true, + name: 'var', + nodes: [ + Word { + isColor: false, + isHex: false, + isUrl: false, + isVariable: true, + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: '--bar', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'word', + value: '--bar', + [Symbol(isClean)]: false, + }, + ], + params: '(--bar)', + parent: [Circular], + raws: { + after: '', + before: ' ', + semicolon: false, + }, + source: { + end: { + column: 16, + line: 1, + offset: 15, + }, + input: Input { + css: 'var(--foo)* var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 13, + line: 1, + offset: 12, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ], + params: '(var(--foo)* var(--bar))', + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 28, + line: 1, + offset: 27, + }, + input: Input { + css: 'calc(var(--foo)* var(--bar))', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ] + +## calc(var(--foo)*var(--bar)) + +> Snapshot 1 + + 'calc(var(--foo)*var(--bar))' + +> Snapshot 2 + + 'calc(var(--foo)*var(--bar))' + +> Snapshot 3 + + [ + Func { + isColor: false, + isVar: false, + name: 'calc', + nodes: [ + Func { + isColor: false, + isVar: true, + name: 'var', + nodes: [ + Word { + isColor: false, + isHex: false, + isUrl: false, + isVariable: true, + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: '--foo', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'word', + value: '--foo', + [Symbol(isClean)]: false, + }, + ], + params: '(--foo)', + parent: [Circular], + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 4, + line: 1, + offset: 3, + }, + input: Input { + css: 'var(--foo)*var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + Operator { + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 11, + line: 1, + offset: 10, + }, + input: Input { + css: 'var(--foo)*var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 11, + line: 1, + offset: 10, + }, + }, + type: 'operator', + value: '*var', + [Symbol(isClean)]: false, + }, + Punctuation { + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 15, + line: 1, + offset: 14, + }, + input: Input { + css: 'var(--foo)*var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 15, + line: 1, + offset: 14, + }, + }, + type: 'punctuation', + value: '(', + [Symbol(isClean)]: false, + }, + Word { + isColor: false, + isHex: false, + isUrl: false, + isVariable: true, + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 1, + line: 1, + offset: 0, + }, + input: Input { + css: 'var(--foo)*var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'word', + value: '--bar', + [Symbol(isClean)]: false, + }, + Punctuation { + parent: [Circular], + raws: { + after: '', + before: '', + }, + source: { + end: { + column: 15, + line: 1, + offset: 14, + }, + input: Input { + css: 'var(--foo)*var(--bar)', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 15, + line: 1, + offset: 14, + }, + }, + type: 'punctuation', + value: ')', + [Symbol(isClean)]: false, + }, + ], + params: '(var(--foo)*var(--bar))', + raws: { + after: '', + before: '', + semicolon: false, + }, + source: { + end: { + column: 27, + line: 1, + offset: 26, + }, + input: Input { + css: 'calc(var(--foo)*var(--bar))', + hasBOM: false, + id: '', + [Symbol(fromOffset cache)]: [ + 0, + ], + }, + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 'func', + [Symbol(isClean)]: false, + }, + ] diff --git a/test/snapshots/func.test.js.snap b/test/snapshots/func.test.js.snap index 610dc5c..ebb0c45 100644 Binary files a/test/snapshots/func.test.js.snap and b/test/snapshots/func.test.js.snap differ