Skip to content

Instantly share code, notes, and snippets.

@dennissterzenbach
Last active May 22, 2017 06:33
Show Gist options
  • Save dennissterzenbach/4208853fcbdaab9cd4fefc982ec1482e to your computer and use it in GitHub Desktop.
Save dennissterzenbach/4208853fcbdaab9cd4fefc982ec1482e to your computer and use it in GitHub Desktop.
simple cli tool to strip CSS variables and replace by their declared values so the resulting file becomes CSS3 cross browser compatible
/**
* Simple JavaScript CLI helper to strip out CSS Variable from your CSS
* and pipe this into a new output file which is completely cross browser
* compatible.
*
* Provided under ISC license:
*
* Copyright (c) 2017, Dennis Sterzenbach
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* @author Dennis Sterzenbach <dennis.sterzenbach@gmail.com>
*/
var fs = require('fs');
let cssFileName;
let outputFileName;
let cssContent;
let verbose = true;
let timingStart = process.hrtime();
let doPrintUsage = false;
let doProcessCSS = true;
if (process.argv.length < 4) {
doPrintUsage = true;
doProcessCSS = false;
}
if (doPrintUsage) {
console.error('Missing Parameters!');
console.log('Usage: cssVariablesCompiler.js <cssInputFileName> <cssOutputFileName>');
}
cssFileName = process.argv[2];
outputFileName = process.argv[3];
console.log('using files:');
console.log('input : ', cssFileName);
console.log('output : ', outputFileName);
console.log('');
if (!cssFileName || cssFileName === '') {
console.error('missing input file');
doProcessCSS = false;
}
if (!outputFileName || outputFileName === '') {
console.error('missing output file');
doProcessCSS = false;
}
if (doProcessCSS) {
console.log('');
cssContent = fs.readFileSync(cssFileName, 'utf-8');
if (verbose) {
console.log('read input file...');
}
let {variables:cssVariables, text:strippedString} = stripVariableDeclarations(cssContent);
if (verbose) {
console.log('grabbed CSS variable declarations...');
}
let result = replaceVariablesByDeclaredValues(strippedString, cssVariables);
if (verbose) {
console.log('replaced CSS variables by their declared values...');
}
fs.writeFileSync(outputFileName, result);
if (verbose) {
console.log('wrote output file.');
elapsedTime('total runtime');
}
}
function stripVariableDeclarations(cssContent) {
let regExp = /([^\(]--[a-zA-Z]+):([^;]+);/gm;
let input = '--test: xyz;'+"\n"+'--test2: 1rem;';
let results;
let variables = {};
let originalTexts = [];
input = cssContent;
while ((results = regExp.exec(input)) !== null) {
variables[ results[1].trim() ] = results[2].trim();
originalTexts.push(results[0]);
}
for (let i = 0; i < originalTexts.length; i++) {
cssContent = cssContent.replace(originalTexts[i], '');
}
return {
variables: variables,
text: cssContent
};
}
function replaceVariablesByDeclaredValues(cssContent, variables) {
let findVarUsageRegExp = /var\((--[a-zA-Z]+)\)/gm;
let input = 'var(--test);'+"\n"+'calc(var(--test2) + 1rem);';
let strippedString;
input = cssContent;
strippedString = cssContent;
// console.log('variables', variables);
while ((results = findVarUsageRegExp.exec(input)) !== null) {
let varName = results[1];
// console.log('varName lookup', varName);
if (variables && variables[varName]) {
value = resolveCSSVariable(variables[varName], 1);
// console.log('varName found', varName, 'value', value);
strippedString = strippedString.replace(results[0], value);
}
}
function resolveCSSVariable(variable, depth) {
let findVarUsageRegExp = /var\((--[a-zA-Z]+)\)/gm;
if (variable && (variable !== '')) {
if ((depth < 10) && (variable.indexOf('var(') !== -1)) {
let varDiscoveryResult = findVarUsageRegExp.exec(variable);
// console.log('resolveCSSVariable', variable, depth, varDiscoveryResult);
if (varDiscoveryResult === null) {
return '';
}
return resolveCSSVariable(varDiscoveryResult[1], ++depth);
}
}
if (variables && variables[variable]) {
return variables[variable];
}
// console.log('resolveCSSVariable return', variable, depth);
return variable;
}
return strippedString;
}
function elapsedTime(commentString) {
let [elapsedSeconds, elapsedNanoseconds] = process.hrtime(timingStart);
console.log(elapsedSeconds + 's ' + (elapsedNanoseconds / 1000000).toFixed(3) + ' ms' + (commentString ? ' - ' + commentString : ''));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment