From f0e0473b0b1bfcfc55a2873928798e87e9e83eae Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Fri, 9 Apr 2021 17:17:02 -0700 Subject: [PATCH 1/4] Enable var This library already just passes calc's right through. I propose doing the same with var and nested calcs and nested vars. We don't need to resolve them, but I do need them not to be swallowed silently in my tests. --- lib/CSSStyleDeclaration.test.js | 42 +++++++++++++++++++++++++++++++++ lib/parsers.js | 12 ++++++++-- lib/parsers.test.js | 42 +++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/lib/CSSStyleDeclaration.test.js b/lib/CSSStyleDeclaration.test.js index 9fa8ed3b..be41e68e 100644 --- a/lib/CSSStyleDeclaration.test.js +++ b/lib/CSSStyleDeclaration.test.js @@ -553,4 +553,46 @@ describe('CSSStyleDeclaration', () => { style.setProperty('width', 'calc(100% - 100px)'); expect(style.getPropertyValue('width')).toEqual('calc(100% - 100px)'); }); + + test('supports nested calc', () => { + const style = new CSSStyleDeclaration(); + style.setProperty('width', 'calc(100% - calc(200px - 100px))'); + expect(style.getPropertyValue('width')).toEqual('calc(100% - calc(200px - 100px))'); + }); + + test('supports var', () => { + const style = new CSSStyleDeclaration(); + style.setProperty('width', 'var(--foo)'); + expect(style.getPropertyValue('width')).toEqual('var(--foo)'); + }); + + test('supports var with fallback', () => { + const style = new CSSStyleDeclaration(); + style.setProperty('width', 'var(--foo, 100px)'); + expect(style.getPropertyValue('width')).toEqual('var(--foo, 100px)'); + }); + + test('supports var with var fallback', () => { + const style = new CSSStyleDeclaration(); + style.setProperty('width', 'var(--foo, var(--bar))'); + expect(style.getPropertyValue('width')).toEqual('var(--foo, var(--bar))'); + }); + + test('supports calc with var inside', () => { + const style = new CSSStyleDeclaration(); + style.setProperty('width', 'calc(100% - var(--foo))'); + expect(style.getPropertyValue('width')).toEqual('calc(100% - var(--foo))'); + }); + + test('supports var with calc inside', () => { + const style = new CSSStyleDeclaration(); + style.setProperty('width', 'var(--foo, calc(var(--bar) + 3px))'); + expect(style.getPropertyValue('width')).toEqual('var(--foo, calc(var(--bar) + 3px))'); + }); + + test('supports color var', () => { + const style = new CSSStyleDeclaration(); + style.setProperty('color', 'var(--foo)'); + expect(style.getPropertyValue('color')).toEqual('var(--foo)'); + }); }); diff --git a/lib/parsers.js b/lib/parsers.js index 8ecdf5e3..8329d4e3 100644 --- a/lib/parsers.js +++ b/lib/parsers.js @@ -19,6 +19,7 @@ exports.TYPES = { KEYWORD: 9, NULL_OR_EMPTY_STR: 10, CALC: 11, + VAR: 12 }; // rough regular expressions @@ -31,9 +32,10 @@ var stringRegEx = /^("[^"]*"|'[^']*')$/; var colorRegEx1 = /^#([0-9a-fA-F]{3,4}){1,2}$/; var colorRegEx2 = /^rgb\(([^)]*)\)$/; var colorRegEx3 = /^rgba\(([^)]*)\)$/; -var calcRegEx = /^calc\(([^)]*)\)$/; +var calcRegEx = /^calc\((.*)\)$/; var colorRegEx4 = /^hsla?\(\s*(-?\d+|-?\d*.\d+)\s*,\s*(-?\d+|-?\d*.\d+)%\s*,\s*(-?\d+|-?\d*.\d+)%\s*(,\s*(-?\d+|-?\d*.\d+)\s*)?\)/; var angleRegEx = /^([-+]?[0-9]*\.?[0-9]+)(deg|grad|rad)$/; +var varRegEx = /^var\((.*)\)$/; // This will return one of the above types based on the passed in string exports.valueType = function valueType(val) { @@ -66,6 +68,9 @@ exports.valueType = function valueType(val) { if (calcRegEx.test(val)) { return exports.TYPES.CALC; } + if (varRegEx.test(val)) { + return exports.TYPES.VAR; + } if (stringRegEx.test(val)) { return exports.TYPES.STRING; } @@ -208,7 +213,7 @@ exports.parsePercent = function parsePercent(val) { // either a length or a percent exports.parseMeasurement = function parseMeasurement(val) { var type = exports.valueType(val); - if (type === exports.TYPES.CALC) { + if (type === exports.TYPES.CALC || type === exports.TYPES.VAR) { return val; } @@ -287,6 +292,9 @@ exports.parseString = function parseString(val) { exports.parseColor = function parseColor(val) { var type = exports.valueType(val); + if (type === exports.TYPES.VAR) { + return val; + } if (type === exports.TYPES.NULL_OR_EMPTY_STR) { return val; } diff --git a/lib/parsers.test.js b/lib/parsers.test.js index 926f7e74..9cebc35b 100644 --- a/lib/parsers.test.js +++ b/lib/parsers.test.js @@ -72,6 +72,41 @@ describe('valueType', () => { expect(output).toEqual(parsers.TYPES.CALC); }); + + it('returns calc from calc(100px * calc(2 * 1))', () => { + let input = 'calc(100px * calc(2 * 1))'; + let output = parsers.valueType(input); + + expect(output).toEqual(parsers.TYPES.CALC); + }); + + it('returns calc from calc(100px * var(--foo))', () => { + let input = 'calc(100px * var(--foo))'; + let output = parsers.valueType(input); + + expect(output).toEqual(parsers.TYPES.CALC); + }); + + it('returns var from var(--foo)', () => { + let input = 'var(--foo)'; + let output = parsers.valueType(input); + + expect(output).toEqual(parsers.TYPES.VAR); + }); + + it('returns var from var(--foo, var(--bar))', () => { + let input = 'var(--foo, var(--bar))'; + let output = parsers.valueType(input); + + expect(output).toEqual(parsers.TYPES.VAR); + }); + + it('returns var from var(--foo, calc(var(--bar) * 2))', () => { + let input = 'var(--foo, calc(var(--bar) * 2))'; + let output = parsers.valueType(input); + + expect(output).toEqual(parsers.TYPES.VAR); + }); }); describe('parseInteger', () => { it.todo('test'); @@ -108,6 +143,13 @@ describe('parseColor', () => { expect(output).toEqual('rgba(5, 5, 5, 0.5)'); }); + it('should pass through vars', () => { + let input = 'var(--foo)'; + let output = parsers.valueType(input); + + expect(output).toEqual(parsers.TYPES.VAR); + }); + it.todo('Add more tests'); }); describe('parseAngle', () => { From 6b0100ed6f8aa67d7f715c8c1e0015a99fe75d4a Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Fri, 9 Apr 2021 17:32:48 -0700 Subject: [PATCH 2/4] fix lint --- lib/parsers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/parsers.js b/lib/parsers.js index 8329d4e3..3558987c 100644 --- a/lib/parsers.js +++ b/lib/parsers.js @@ -19,7 +19,7 @@ exports.TYPES = { KEYWORD: 9, NULL_OR_EMPTY_STR: 10, CALC: 11, - VAR: 12 + VAR: 12, }; // rough regular expressions From 2f314f9a8a4e347255e85bdeb8a0b446ac9ef055 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Mon, 8 Jul 2024 13:26:55 +1000 Subject: [PATCH 3/4] update with review suggestions --- lib/CSSStyleDeclaration.js | 4 +++- lib/parsers.js | 12 ++---------- lib/parsers.test.js | 9 ++++----- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/lib/CSSStyleDeclaration.js b/lib/CSSStyleDeclaration.js index 0a180f6f..d7a75663 100644 --- a/lib/CSSStyleDeclaration.js +++ b/lib/CSSStyleDeclaration.js @@ -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; diff --git a/lib/parsers.js b/lib/parsers.js index e0aa6e54..3c3b6952 100644 --- a/lib/parsers.js +++ b/lib/parsers.js @@ -18,8 +18,7 @@ exports.TYPES = { ANGLE: 8, KEYWORD: 9, NULL_OR_EMPTY_STR: 10, - CALC: 11, - VAR: 12, + CALC: 11 }; // rough regular expressions @@ -36,7 +35,6 @@ var colorRegEx4 = /^hsla?\(\s*(-?\d+|-?\d*.\d+)\s*,\s*(-?\d+|-?\d*.\d+)%\s*,\s*(-?\d+|-?\d*.\d+)%\s*(,\s*(-?\d+|-?\d*.\d+)\s*)?\)/; var calcRegEx = /^calc\((.*)\)$/; var angleRegEx = /^([-+]?[0-9]*\.?[0-9]+)(deg|grad|rad)$/; -var varRegEx = /^var\((.*)\)$/; // This will return one of the above types based on the passed in string exports.valueType = function valueType(val) { @@ -69,9 +67,6 @@ exports.valueType = function valueType(val) { if (calcRegEx.test(val)) { return exports.TYPES.CALC; } - if (varRegEx.test(val)) { - return exports.TYPES.VAR; - } if (stringRegEx.test(val)) { return exports.TYPES.STRING; } @@ -214,7 +209,7 @@ exports.parsePercent = function parsePercent(val) { // either a length or a percent exports.parseMeasurement = function parseMeasurement(val) { var type = exports.valueType(val); - if (type === exports.TYPES.CALC || type === exports.TYPES.VAR) { + if (type === exports.TYPES.CALC) { return val; } @@ -293,9 +288,6 @@ exports.parseString = function parseString(val) { exports.parseColor = function parseColor(val) { var type = exports.valueType(val); - if (type === exports.TYPES.VAR) { - return val; - } if (type === exports.TYPES.NULL_OR_EMPTY_STR) { return val; } diff --git a/lib/parsers.test.js b/lib/parsers.test.js index 78009786..a792e1ed 100644 --- a/lib/parsers.test.js +++ b/lib/parsers.test.js @@ -91,21 +91,21 @@ describe('valueType', () => { let input = 'var(--foo)'; let output = parsers.valueType(input); - expect(output).toEqual(parsers.TYPES.VAR); + expect(output).toEqual(parsers.TYPES.KEYWORD); }); it('returns var from var(--foo, var(--bar))', () => { let input = 'var(--foo, var(--bar))'; let output = parsers.valueType(input); - expect(output).toEqual(parsers.TYPES.VAR); + expect(output).toEqual(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); - expect(output).toEqual(parsers.TYPES.VAR); + expect(output).toEqual(parsers.TYPES.KEYWORD); }); }); describe('parseInteger', () => { @@ -143,12 +143,11 @@ describe('parseColor', () => { expect(output).toEqual('rgba(5, 5, 5, 0.5)'); }); - it('should pass through vars', () => { let input = 'var(--foo)'; let output = parsers.valueType(input); - expect(output).toEqual(parsers.TYPES.VAR); + expect(output).toEqual(parsers.TYPES.KEYWORD); }); it.each([ From 421ad6b62647ee03304c8881be5f17fd3c8a3a16 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Mon, 8 Jul 2024 13:27:23 +1000 Subject: [PATCH 4/4] fix lint --- lib/parsers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/parsers.js b/lib/parsers.js index 3c3b6952..cfef3a28 100644 --- a/lib/parsers.js +++ b/lib/parsers.js @@ -18,7 +18,7 @@ exports.TYPES = { ANGLE: 8, KEYWORD: 9, NULL_OR_EMPTY_STR: 10, - CALC: 11 + CALC: 11, }; // rough regular expressions