Skip to content

Commit

Permalink
fix(issue:4224, issue:3777) CSS custom property
Browse files Browse the repository at this point in the history
* Fixes CSS custom property handling to address issue less#4224 and issue
  less#3777.
* Added new CSS custom property tests.
  • Loading branch information
puckowski committed Dec 7, 2024
1 parent 773e157 commit fe7ab14
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 5 deletions.
9 changes: 9 additions & 0 deletions packages/less/src/less/functions/math-helper.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import Call from '../tree/call';
import CustomProperty from '../tree/custom-property';
import Dimension from '../tree/dimension';

const MathHelper = (fn, unit, n) => {
if (n instanceof Call && n.name === 'var') {
if (n.args && n.args.length === 1) {
return new Call(fn.name, [new CustomProperty(n.args[0].toCSS(), n._index, n._fileInfo)], n._index, n._fileInfo);
} else {
throw { type: 'Argument', message: 'var must contain one expression' };
}
}
if (!(n instanceof Dimension)) {
throw { type: 'Argument', message: 'argument must be a number' };
}
Expand Down
16 changes: 14 additions & 2 deletions packages/less/src/less/parser/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,18 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*:/))) { return name[1]; }
},

//
// The custom property part of a variable definition.
//
// --fink:
//
customProperty: function () {
var name;
if (parserInput.currentChar() === '-' && (name = parserInput.$re(/^(--[\w-]+)\s*:/))) {
return name[1];
}
},

//
// Call a variable value to retrieve a detached ruleset
// or a value from a detached ruleset's rules.
Expand Down Expand Up @@ -1558,7 +1570,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {

parserInput.save();

name = this.variable() || this.ruleProperty();
name = this.variable() || this.customProperty() || this.ruleProperty();
if (name) {
isVariable = typeof name === 'string';

Expand All @@ -1577,7 +1589,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
merge = !isVariable && name.length > 1 && name.pop().value;

// Custom property values get permissive parsing
if (name[0].value && name[0].value.slice(0, 2) === '--') {
if (isVariable && name.startsWith('--')) {
value = this.permissiveValue(/[;}]/);
}
// Try to store values as anonymous
Expand Down
18 changes: 18 additions & 0 deletions packages/less/src/less/tree/custom-property.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* eslint-disable no-prototype-builtins */
import Node from './node';

const CustomProperty = function (name, index, currentFileInfo) {
this.name = name;
this._index = index;
this._fileInfo = currentFileInfo;
};

CustomProperty.prototype = Object.assign(new Node(), {
type: 'CustomProperty',

genCSS: function (context, output) {
output.add('var(' + this.name + ')');
}
});

export default CustomProperty;
47 changes: 45 additions & 2 deletions packages/less/src/less/tree/operation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Node from './node';
import Color from './color';
import Dimension from './dimension';
import * as Constants from '../constants';
import Call from './call';
const MATH = Constants.Math;


Expand All @@ -19,7 +20,15 @@ Operation.prototype = Object.assign(new Node(), {
},

eval(context) {
let a = this.operands[0].eval(context), b = this.operands[1].eval(context), op;
var a = this.evalVariable(context, this.operands[0])
if (!a) {
a = this.operands[0].eval(context)
}
var b = this.evalVariable(context, this.operands[1]);
if (!b) {
b = this.operands[1].eval(context);
}
var op;

if (context.isMathOn(this.op)) {
op = this.op === './' ? '/' : this.op;
Expand Down Expand Up @@ -56,7 +65,41 @@ Operation.prototype = Object.assign(new Node(), {
output.add(' ');
}
this.operands[1].genCSS(context, output);
}
},

find: function (obj, fun) {
for (var i_2 = 0, r = void 0; i_2 < obj.length; i_2++) {
r = fun.call(obj, obj[i_2]);
if (r) {
return r;
}
}
return null;
},

evalVariable: function (context, operand) {
if (operand.name === 'var' && operand.args.length === 1) {
var varName = operand.args[0].toCSS();
var variable = this.find(context.frames, function (frame) {
var v = frame.variable(varName);
if (v) {
if (v.important) {
var importantScope = context.importantScope[context.importantScope.length - 1];
importantScope.important = v.important;
}
// If in calc, wrap vars in a function call to cascade evaluate args first
if (context.inCalc) {
return (new Call('_SELF', [v.value])).eval(context);
}
else {
return v.value.eval(context);
}
}
});

return variable;
}
},
});

export default Operation;
2 changes: 1 addition & 1 deletion packages/less/src/less/tree/ruleset.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ Ruleset.prototype = Object.assign(new Node(), {
variables() {
if (!this._variables) {
this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
if (r instanceof Declaration && r.variable === true) {
if (r instanceof Declaration && (r.variable === true || (typeof r.name ==='string' && r.name.startsWith('--')))) {
hash[r.name] = r;
}
// when evaluating variables in an import statement, imports have not been eval'd
Expand Down
16 changes: 16 additions & 0 deletions packages/test-data/css/_main/custom-property.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.test {
--basic-deg: 20deg;
--basic-deg-tan: tan(var(--basic-deg));
}
.test2 {
--some-var: 5%;
prop: min(95%, 10px);
}
.test3 {
--some-var: 55%;
prop: min(60%, 15px);
}
.test4 {
color: red;
--other-color: green;
}
19 changes: 19 additions & 0 deletions packages/test-data/less/_main/custom-property.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.test {
--basic-deg: 20deg;
--basic-deg-tan: tan(var(--basic-deg));
}

.test2 {
--some-var: 5%;
prop: min(100% - var(--some-var), 10px);
}

.test3 {
--some-var: 55%;
prop: min(var(--some-var) + 5%, 15px);
}

.test4 {
color: red;
--other-color: green;
}

0 comments on commit fe7ab14

Please sign in to comment.