Created
June 17, 2021 12:28
-
-
Save studentIvan/eaffd0cffc10e2ec0701a34c83b48cf5 to your computer and use it in GitHub Desktop.
Postcss plugin variables rename
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-plusplus */ | |
/* eslint-disable func-names */ | |
/* eslint-disable no-restricted-syntax */ | |
const fs = require('fs'); | |
const path = require('path'); | |
/** load the existing json map with access to write and read */ | |
const variablesMapJSON = path.join(__dirname, '/variables-map.json'); | |
/** | |
* alphabetGetter is something easy to understand for the human mind | |
* just use alphabetGetter.next() to receive the next variable name | |
*/ | |
const alphabetGetter = { | |
get alphabetEnglish() { | |
return Array.from({ length: 26 }, (_, i) => String.fromCharCode('a'.charCodeAt(0) + i)); | |
}, | |
/** | |
* Provide the existing giving names map to the alphabetGetter so it won't overwrite them | |
* @param {Object<string, string>} variablesDeclaredToUse | |
*/ | |
init(variablesDeclaredToUse) { | |
this.alphabet = this.alphabetEnglish; | |
/** five levels is a lot */ | |
for (const rangeOrder of ['1', '2', '3', '4', '5']) { | |
this.alphabet = this.alphabet.concat(this.alphabetEnglish.map(l => `${ l }${ rangeOrder }`)); | |
} | |
const usingChars = Object.values(variablesDeclaredToUse).map(l => l.replace('--', '')).sort(); | |
this.index = !usingChars.length ? -1 : this.alphabet.indexOf(usingChars[usingChars.length - 1]); | |
}, | |
/** | |
* @returns {string} the next variable short name with -- | |
*/ | |
next() { | |
this.index += 1; | |
if (!this.alphabet[this.index]) { | |
throw new Error('alphabet is limited'); | |
} | |
return `--${ this.alphabet[this.index] }`; | |
}, | |
}; | |
/** rename css variables declaration in the css */ | |
module.exports = () => { | |
return { | |
postcssPlugin: 'rename-css-variables', | |
/** support the postcss modern syntax */ | |
Once(css) { | |
/** we don't want to spend the developer machine resources - be eco bitch */ | |
const PRODUCTION_MODE = process.env.NODE_ENV !== 'development' && process.env.NODE_ENV !== 'test'; | |
if (!PRODUCTION_MODE) return; | |
/** @type {Object<string, string>} */ | |
const variablesDeclaredToUse = JSON.parse(fs.readFileSync(variablesMapJSON, { encoding: 'utf8' })) || {}; | |
/** no try/catch here, because it bad for performance... */ | |
alphabetGetter.init(variablesDeclaredToUse); | |
/** Have the variables been updated or not? */ | |
let variablesMapWereChanged = false; | |
const indexVariable = (variableName) => { | |
if (!(variableName in variablesDeclaredToUse)) { | |
variablesDeclaredToUse[variableName] = alphabetGetter.next(); | |
variablesMapWereChanged = true; | |
} | |
}; | |
const optimizeVariable = (variableName) => { | |
return variableName in variablesDeclaredToUse ? variablesDeclaredToUse[variableName] : variableName; | |
}; | |
/** walking first time - indexing... */ | |
css.walk((rule) => { | |
if (rule.nodes === undefined) return; | |
rule.nodes.filter(node => node.type === 'decl').forEach((node) => { | |
if (/^--[a-z0-9-_]{4,}$/i.test(node.prop)) { | |
indexVariable(node.prop); | |
} | |
if (node.value) { | |
[...node.value.matchAll(/var\((--[^)]{4,})\)/g)].map(v => v[1]).forEach(indexVariable); | |
} | |
}); | |
}); | |
/** walking second time - patching... */ | |
css.walk((rule) => { | |
if (rule.nodes === undefined) return; | |
rule.nodes.filter(node => node.type === 'decl').forEach((node) => { | |
if (/^--[a-z0-9-_]{4,}$/i.test(node.prop)) { | |
node.prop = optimizeVariable(node.prop); | |
} | |
if (node.value) { | |
const usingVariables = [...node.value.matchAll(/var\((--[^)]{4,})\)/g)].map(v => v[1]); | |
if (usingVariables.length) { | |
usingVariables.forEach((usingVariable) => { | |
node.value = node.value.replace(usingVariable, optimizeVariable(usingVariable)); | |
}); | |
} | |
} | |
}); | |
}); | |
/** if something has changed - save the map... */ | |
if (variablesMapWereChanged) { | |
fs.writeFileSync(variablesMapJSON, JSON.stringify(variablesDeclaredToUse, null, 2), { encoding: 'utf8' }); | |
} | |
}, | |
}; | |
}; | |
module.exports.postcss = true; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment