Skip to content

Commit

Permalink
Support nested var() and nested calc()
Browse files Browse the repository at this point in the history
Fixes jsdom#125, closes jsdom#127
  • Loading branch information
asamuzaK committed Dec 20, 2024
1 parent 8a19acd commit 37b0abb
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 11 deletions.
4 changes: 3 additions & 1 deletion lib/CSSStyleDeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ CSSStyleDeclaration.prototype = {
this.removeProperty(name);
return;
}
var isCustomProperty = name.indexOf('--') === 0;
var isCustomProperty =
name.indexOf('--') === 0 ||
(typeof value === 'string' && /^var\(--[-\w]+,?.*\)$/.test(value));
if (isCustomProperty) {
this._setProperty(name, value, priority);
return;
Expand Down
10 changes: 5 additions & 5 deletions lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
********************************************************************/
'use strict';

const { isColor, resolve } = require('@asamuzakjp/css-color');
const { cssCalc, isColor, resolve } = require('@asamuzakjp/css-color');

exports.TYPES = {
INTEGER: 1,
Expand All @@ -27,7 +27,7 @@ var lengthRegEx = /^(0|[-+]?[0-9]*\.?[0-9]+(in|cm|em|mm|pt|pc|px|ex|rem|vh|vw|ch
var percentRegEx = /^[-+]?[0-9]*\.?[0-9]+%$/;
var urlRegEx = /^url\(\s*([^)]*)\s*\)$/;
var stringRegEx = /^("[^"]*"|'[^']*')$/;
var calcRegEx = /^calc\(([^)]*)\)$/;
var calcRegEx = /^(?:abs|calc|sign)\(/;
var angleRegEx = /^([-+]?[0-9]*\.?[0-9]+)(deg|grad|rad)$/;

// This will return one of the above types based on the passed in string
Expand All @@ -38,11 +38,9 @@ exports.valueType = function valueType(val) {
if (typeof val === 'number') {
val = val.toString();
}

if (typeof val !== 'string') {
return undefined;
}

if (integerRegEx.test(val)) {
return exports.TYPES.INTEGER;
}
Expand Down Expand Up @@ -161,7 +159,9 @@ exports.parsePercent = function parsePercent(val) {
exports.parseMeasurement = function parseMeasurement(val) {
var type = exports.valueType(val);
if (type === exports.TYPES.CALC) {
return val;
return cssCalc(val, {
format: 'specifiedValue',
});
}

var length = exports.parseLength(val);
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
],
"main": "./lib/CSSStyleDeclaration.js",
"dependencies": {
"@asamuzakjp/css-color": "^2.5.0",
"@asamuzakjp/css-color": "^2.6.5",
"rrweb-cssom": "^0.7.1"
},
"devDependencies": {
Expand Down
57 changes: 57 additions & 0 deletions test/CSSStyleDeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -748,4 +748,61 @@ describe('CSSStyleDeclaration', () => {
assert.strictEqual(style.getPropertyValue(property), 'calc(100% - 100px)');
});
}

it('supports nested calc', () => {
const style = new CSSStyleDeclaration();
style.setProperty('width', 'calc(100% - calc(200px - 100px))');
assert.strictEqual(style.getPropertyValue('width'), 'calc(100% - 100px)');
});

it('supports nested calc', () => {
const style = new CSSStyleDeclaration();
style.setProperty('width', 'calc(100% * calc(2 / 3))');
assert.strictEqual(style.getPropertyValue('width'), 'calc(66.6667%)');
});

it('supports var', () => {
const style = new CSSStyleDeclaration();
style.setProperty('width', 'var(--foo)');
assert.strictEqual(style.getPropertyValue('width'), 'var(--foo)');
});

it('supports var with fallback', () => {
const style = new CSSStyleDeclaration();
style.setProperty('width', 'var(--foo, 100px)');
assert.strictEqual(style.getPropertyValue('width'), 'var(--foo, 100px)');
});

it('supports var with var fallback', () => {
const style = new CSSStyleDeclaration();
style.setProperty('width', 'var(--foo, var(--bar))');
assert.strictEqual(style.getPropertyValue('width'), 'var(--foo, var(--bar))');
});

it('supports calc with var inside', () => {
const style = new CSSStyleDeclaration();
style.setProperty('width', 'calc(100% - var(--foo))');
assert.strictEqual(style.getPropertyValue('width'), 'calc(100% - var(--foo))');
});

it('supports var with calc inside', () => {
const style = new CSSStyleDeclaration();
style.setProperty('width', 'var(--foo, calc(var(--bar) + 3px))');
assert.strictEqual(style.getPropertyValue('width'), 'var(--foo, calc(var(--bar) + 3px))');
});

it('supports color var', () => {
const style = new CSSStyleDeclaration();
style.setProperty('color', 'var(--foo)');
assert.strictEqual(style.getPropertyValue('color'), 'var(--foo)');
});

it('should not normalize if var() is included', () => {
const style = new CSSStyleDeclaration();
style.setProperty('width', 'calc( /* comment */ 100% - calc(var(--foo) *2 ))');
assert.strictEqual(
style.getPropertyValue('width'),
'calc( /* comment */ 100% - calc(var(--foo) *2 ))'
);
});
});
36 changes: 36 additions & 0 deletions test/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,43 @@ describe('valueType', () => {

assert.strictEqual(output, parsers.TYPES.CALC);
});

it('returns calc from calc(100px * calc(2 * 1))', () => {
let input = 'calc(100px * calc(2 * 1))';
let output = parsers.valueType(input);

assert.strictEqual(output, parsers.TYPES.CALC);
});

it('returns calc from calc(100px * var(--foo))', () => {
let input = 'calc(100px * var(--foo))';
let output = parsers.valueType(input);

assert.strictEqual(output, parsers.TYPES.CALC);
});

it('returns var from var(--foo)', () => {
let input = 'var(--foo)';
let output = parsers.valueType(input);

assert.strictEqual(output, parsers.TYPES.KEYWORD);
});

it('returns var from var(--foo, var(--bar))', () => {
let input = 'var(--foo, var(--bar))';
let output = parsers.valueType(input);

assert.strictEqual(output, parsers.TYPES.KEYWORD);
});

it('returns var from var(--foo, calc(var(--bar) * 2))', () => {
let input = 'var(--foo, calc(var(--bar) * 2))';
let output = parsers.valueType(input);

assert.strictEqual(output, parsers.TYPES.KEYWORD);
});
});

describe('parseInteger', () => {
it.todo('test');
});
Expand Down

0 comments on commit 37b0abb

Please sign in to comment.