Merge pull request #759 from vector-im/move-scope-down

Refactor out global variables in postcss plugins
This commit is contained in:
R Midhun Suresh 2022-06-20 12:14:06 +05:30 committed by GitHub
commit 5a3cf03f0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 24 deletions

View file

@ -30,12 +30,7 @@ const valueParser = require("postcss-value-parser");
* The actual derivation is done outside the plugin in a callback.
*/
let aliasMap;
let resolvedMap;
let baseVariables;
let isDark;
function getValueFromAlias(alias) {
function getValueFromAlias(alias, {aliasMap, baseVariables, resolvedMap}) {
const derivedVariable = aliasMap.get(alias);
return baseVariables.get(derivedVariable) ?? resolvedMap.get(derivedVariable);
}
@ -68,14 +63,15 @@ function parseDeclarationValue(value) {
return variables;
}
function resolveDerivedVariable(decl, derive) {
function resolveDerivedVariable(decl, derive, maps, isDark) {
const { baseVariables, resolvedMap } = maps;
const RE_VARIABLE_VALUE = /(?:--)?((.+)--(.+)-(.+))/;
const variableCollection = parseDeclarationValue(decl.value);
for (const variable of variableCollection) {
const matches = variable.match(RE_VARIABLE_VALUE);
if (matches) {
const [, wholeVariable, baseVariable, operation, argument] = matches;
const value = baseVariables.get(baseVariable) ?? getValueFromAlias(baseVariable);
const value = baseVariables.get(baseVariable) ?? getValueFromAlias(baseVariable, maps);
if (!value) {
throw new Error(`Cannot derive from ${baseVariable} because it is neither defined in config nor is it an alias!`);
}
@ -85,7 +81,7 @@ function resolveDerivedVariable(decl, derive) {
}
}
function extract(decl) {
function extract(decl, {aliasMap, baseVariables}) {
if (decl.variable) {
// see if right side is of form "var(--foo)"
const wholeVariable = decl.value.match(/var\(--(.+)\)/)?.[1];
@ -100,7 +96,7 @@ function extract(decl) {
}
}
function addResolvedVariablesToRootSelector(root, {Rule, Declaration}) {
function addResolvedVariablesToRootSelector(root, {Rule, Declaration}, {resolvedMap}) {
const newRule = new Rule({ selector: ":root", source: root.source });
// Add derived css variables to :root
resolvedMap.forEach((value, key) => {
@ -110,7 +106,7 @@ function addResolvedVariablesToRootSelector(root, {Rule, Declaration}) {
root.append(newRule);
}
function populateMapWithDerivedVariables(map, cssFileLocation) {
function populateMapWithDerivedVariables(map, cssFileLocation, {resolvedMap, aliasMap}) {
const location = cssFileLocation.match(/(.+)\/.+\.css/)?.[1];
const derivedVariables = [
...([...resolvedMap.keys()].filter(v => !aliasMap.has(v))),
@ -133,10 +129,10 @@ function populateMapWithDerivedVariables(map, cssFileLocation) {
* @param {Map} opts.compiledVariables - A map that stores derived variables so that manifest source sections can be produced
*/
module.exports = (opts = {}) => {
aliasMap = new Map();
resolvedMap = new Map();
baseVariables = new Map();
isDark = false;
const aliasMap = new Map();
const resolvedMap = new Map();
const baseVariables = new Map();
const maps = { aliasMap, resolvedMap, baseVariables };
return {
postcssPlugin: "postcss-compile-variables",
@ -147,16 +143,16 @@ module.exports = (opts = {}) => {
// If this is a runtime theme, don't derive variables.
return;
}
isDark = cssFileLocation.includes("dark=true");
const isDark = cssFileLocation.includes("dark=true");
/*
Go through the CSS file once to extract all aliases and base variables.
We use these when resolving derived variables later.
*/
root.walkDecls(decl => extract(decl));
root.walkDecls(decl => resolveDerivedVariable(decl, opts.derive));
addResolvedVariablesToRootSelector(root, {Rule, Declaration});
root.walkDecls(decl => extract(decl, maps));
root.walkDecls(decl => resolveDerivedVariable(decl, opts.derive, maps, isDark));
addResolvedVariablesToRootSelector(root, {Rule, Declaration}, maps);
if (opts.compiledVariables){
populateMapWithDerivedVariables(opts.compiledVariables, cssFileLocation);
populateMapWithDerivedVariables(opts.compiledVariables, cssFileLocation, maps);
}
// Also produce a mapping from alias to completely resolved color
const resolvedAliasMap = new Map();

View file

@ -16,7 +16,6 @@ limitations under the License.
const valueParser = require("postcss-value-parser");
const resolve = require("path").resolve;
let cssPath;
function colorsFromURL(url, colorMap) {
const params = new URL(`file://${url}`).searchParams;
@ -36,7 +35,7 @@ function colorsFromURL(url, colorMap) {
return [primaryColor, secondaryColor];
}
function processURL(decl, replacer, colorMap) {
function processURL(decl, replacer, colorMap, cssPath) {
const value = decl.value;
const parsed = valueParser(value);
parsed.walk(node => {
@ -84,8 +83,8 @@ module.exports = (opts = {}) => {
Go through each declaration and if it contains an URL, replace the url with the result
of running replacer(url)
*/
cssPath = root.source?.input.file.replace(/[^/]*$/, "");
root.walkDecls(decl => processURL(decl, opts.replacer, colorMap));
const cssPath = root.source?.input.file.replace(/[^/]*$/, "");
root.walkDecls(decl => processURL(decl, opts.replacer, colorMap, cssPath));
},
};
};