From 3f99e9d49fac620405dcad48556f5c4dfcf916c4 Mon Sep 17 00:00:00 2001 From: Peter Muessig Date: Fri, 21 Feb 2020 08:59:18 +0100 Subject: [PATCH] [FEATURE] Keep linking of less vars for css vars (#115) --- lib/index.js | 5 +- lib/plugin/css-variables-collector.js | 2 +- lib/plugin/css-variables-pointer.js | 73 +++++++++++++++++++ .../complex/test-cssvars-variables.css | 3 +- test/fixtures/complex/test.less | 1 + 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 lib/plugin/css-variables-pointer.js diff --git a/lib/index.js b/lib/index.js index 80a2fc0c..37361405 100644 --- a/lib/index.js +++ b/lib/index.js @@ -302,7 +302,10 @@ Builder.prototype.build = function(options) { if (err) { reject(err); } else { - result.cssVariables = tree.toCSS(assign({}, options.compiler)); + const CSSVariablesPointerPlugin = require("./plugin/css-variables-pointer"); + result.cssVariables = tree.toCSS(assign({}, options.compiler, { + plugins: [new CSSVariablesPointerPlugin()] + })); resolve(result); } }); diff --git a/lib/plugin/css-variables-collector.js b/lib/plugin/css-variables-collector.js index 250ece86..05b3ffde 100644 --- a/lib/plugin/css-variables-collector.js +++ b/lib/plugin/css-variables-collector.js @@ -141,7 +141,7 @@ CSSVariablesCollectorPlugin.prototype = { visitVariable(node, visitArgs) { // convert less variables into CSS variables if (this._isRelevant()) { - return new less.tree.Call("var", [new less.tree.Anonymous(node.name.replace(/^@/, "--", node.index, node.currentFileInfo, node.mapLines))]); + return new less.tree.Call("var", [new less.tree.Anonymous(node.name.replace(/^@/, "--"), node.index, node.currentFileInfo, node.mapLines)]); } return node; }, diff --git a/lib/plugin/css-variables-pointer.js b/lib/plugin/css-variables-pointer.js new file mode 100644 index 00000000..e509dfb0 --- /dev/null +++ b/lib/plugin/css-variables-pointer.js @@ -0,0 +1,73 @@ +// Copyright 2020 SAP SE. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http: //www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific +// language governing permissions and limitations under the License. + +"use strict"; + +const less = require("../thirdparty/less"); + +const CSSVariablesPointerPlugin = module.exports = function(config) { + this.config = config; + // eslint-disable-next-line new-cap + this.native = new less.tree.visitor(this); + this.ruleStack = []; + this.callStack = []; + this.mVars = {}; +}; + +CSSVariablesPointerPlugin.prototype = { + + isPreEvalVisitor: true, + isReplacing: true, + + run(root) { + return this.native.visit(root); + }, + + visitRule(node, visitArgs) { + // store the rule context for the call variable extraction + this.ruleStack.push(node); + // replace the direct less variable assignment with the css variable + if (Array.isArray(node.name) && node.name[0] instanceof less.tree.Keyword && this.mVars[node.name[0].value]) { + node.value = new less.tree.Anonymous(this.mVars[node.name[0].value], node.index, node.currentFileInfo, node.mapLines); + } + return node; + }, + + visitRuleOut(node) { + // remove rule context + this.ruleStack.pop(); + return node; + }, + + visitCall(node, visitArgs) { + // store the call context for the call variable extraction + this.callStack.push(node); + return node; + }, + + visitCallOut(node, visitArgs) { + // remove call context + this.callStack.pop(); + return node; + }, + + visitVariable(node, visitArgs) { + // collect less variables to css variables mapping + if (this.callStack.length == 0 && this.ruleStack.length > 0 && this.ruleStack[this.ruleStack.length - 1].variable) { + this.mVars["--" + this.ruleStack[0].name.substr(1)] = "var(" + node.name.replace(/^@/, "--") + ")"; + } + return node; + } + +}; diff --git a/test/expected/complex/test-cssvars-variables.css b/test/expected/complex/test-cssvars-variables.css index 13225101..9ab118db 100644 --- a/test/expected/complex/test-cssvars-variables.css +++ b/test/expected/complex/test-cssvars-variables.css @@ -1,6 +1,7 @@ :root { --link-color: #428bca; --link-color-hover: #3071a9; - --var: 9%; + --link-color-active: var(--link-color); + --var: var(--a); --a: 9%; } diff --git a/test/fixtures/complex/test.less b/test/fixtures/complex/test.less index a53d54cb..feec2fe9 100644 --- a/test/fixtures/complex/test.less +++ b/test/fixtures/complex/test.less @@ -1,6 +1,7 @@ // Variables @link-color: #428bca; // sea blue @link-color-hover: darken(@link-color, 10%); +@link-color-active: @link-color; // Usage a,