UNPKG

less-var-to-css-var

Version:
212 lines (164 loc) 6.18 kB
#!/usr/bin/env node const fs = require('fs'); const pkg = require('../package.json'); const isExecOnCLI = require.main === module; // usage // node index.js -i '~/styles/variables.less' -o '~/styles/variables-css2.less' -t ':root' -h "@import '/src/styles/variables.less';" const lessVarToCssVar = (opts) => { let inputPath = undefined; let outputPath = undefined; let scopeTag = ':root'; let header = ''; let jsOutputPath = undefined; let jsVar = 'COLOR'; let jsheader = ''; // 没有传参进来,认为是 node cil 执行,读取 argv if (!isExecOnCLI && opts) { console.log(`\n⚡️ less-var-to-css-var via JS (v${pkg.version})\n`); if (opts.inputPath) inputPath = opts.inputPath; if (opts.outputPath) outputPath = opts.outputPath; if (opts.scopeTag) scopeTag = opts.scopeTag; if (opts.header) header = opts.header; if (opts.jsOutputPath) jsOutputPath = opts.jsOutputPath; if (opts.jsVar) jsVar = opts.jsVar; if (opts.jsheader) jsheader = opts.jsheader; } if (isExecOnCLI) { console.log(`\n⚡️ less-var-to-css-var via CIL (v${pkg.version})\n`); process.argv.forEach((v, i, arr) => { if (i < 2) return; // 找到命令名称,那下一个一定是值 if (v === '-i' && arr[i + 1]) inputPath = arr[i + 1]; if (v === '-o' && arr[i + 1]) outputPath = arr[i + 1]; if (v === '-t' && arr[i + 1]) scopeTag = arr[i + 1]; if (v === '-h' && arr[i + 1]) header = arr[i + 1]; }); } if (!inputPath || !outputPath || !scopeTag) { console.log(''.padEnd(32, '-')); console.log('\n⚠️ Missing Argv!\n'); console.log(''.padEnd(32, '-')); return; } // Avoid too long formatting const vars = fs.readFileSync(inputPath, 'utf-8').replace(/,\n/g, ','); const matchs = vars.match(/^@.*/gm); // eslint-disable-next-line array-callback-return,consistent-return const allCssVars = matchs.map((m) => { const mv = m.match(/^@(.*?)\s?:\s?(.*);/m); // eslint-disable-next-line @typescript-eslint/prefer-optional-chain if (mv && mv[1]) { return { key: mv[1] || '', value: mv[2] || '', }; } }); const __CODE_GEN_COMMENT__ = `/\*\n ⚠️ PLEASE DO NOT MODIFY THIS FILE!\n\n All code is automatically generated by plugin \`less-var-to-css-var\`.\n*\/`; const __ESLINT_STR__ = `/\* eslint-disable max-len \*/`; // // output CSS if (outputPath) { let ROOT_CSS_HEADER = `${__CODE_GEN_COMMENT__}\n${scopeTag} {\n`; if (header) { ROOT_CSS_HEADER = `${__CODE_GEN_COMMENT__}\n${header}\n\n${scopeTag} {\n`; } const ROOT_CSS_FOOTER = `}\n`; let ROOT_CSS_CONTENT = ''; allCssVars.forEach((item) => { // --screen-md: @screen-md; if (!item?.key) return; let val = `@${item.key}`; // Use real CSS values instead of the --a: @a; mapping if (opts.useRealValue) { // 去找一下有没有这个 key 先 let fValue = ''; if (item.value.startsWith('@')) { const fKey = item.value.replace('@', ''); fValue = allCssVars.find((item) => item?.key === fKey)?.value; } val = fValue || `${item.value}`; } // Replace the string of the less variable if (opts.useRealValue && opts.useRealValueFilterLessVar) { val = /[@]/.test(item.value) ? opts.useRealValueFilterLessVar : item.value; } ROOT_CSS_CONTENT += ` --${item.key}: ${val};\n`; }); // Dark Css Vars if (opts.scopeTagDark) { let DARK_CSS_HEADER = `\n${opts.scopeTagDark} {\n`; let DARK_CSS_CONTENT = ''; const DARK_CSS_FOOTER = `}\n`; let ROOT_CSS_CONTENT_CLONE = ''; // get all -auto-.*--dark vars const darkCssVars = ROOT_CSS_CONTENT?.match(/--.*--dark:.*/gm, ''); ROOT_CSS_CONTENT_CLONE = ROOT_CSS_CONTENT; // remove all --dark vars if (opts.removeAllRootDarkVars) { // ROOT_CSS_CONTENT = ROOT_CSS_CONTENT.replaceAll(/\n.*--.*--dark:.*/gm, ''); ROOT_CSS_CONTENT_CLONE = ROOT_CSS_CONTENT.replaceAll(/\n.*--.*--dark:.*/gm, ''); } darkCssVars?.forEach((item) => { if (opts.removeAllDarkDarkSuffix) { item = item.replace('--dark:', ':'); } DARK_CSS_CONTENT += ` ${item}\n`; }) const CSS_RESULT = `${ROOT_CSS_HEADER}${ROOT_CSS_CONTENT_CLONE}${ROOT_CSS_FOOTER}` + `${DARK_CSS_HEADER}${DARK_CSS_CONTENT}${DARK_CSS_FOOTER}`; console.log(CSS_RESULT); // output ROOT + DARK CSS fs.writeFileSync(outputPath, CSS_RESULT); // return; } else { // output ROOT CSS fs.writeFileSync(outputPath, `${ROOT_CSS_HEADER}${ROOT_CSS_CONTENT}${ROOT_CSS_FOOTER}`); } } // // output JS if (jsOutputPath) { let JS_HEADER = `${__CODE_GEN_COMMENT__}\n\n${__ESLINT_STR__}\nexport const ${jsVar} = {\n`; if (header) { JS_HEADER = `${__CODE_GEN_COMMENT__}\n\n${__ESLINT_STR__}\n${jsheader}\n\nexport const ${jsVar} = {\n`; } // KEEP FORMAT ------------ const JS_FOOTER = `}; `; // KEEP FORMAT ------------ let JS_CONTENT = ''; allCssVars.forEach((item) => { // --screen-md: @screen-md; if (!item?.key) return; // 过滤掉不需要的符号 item.value = item.value.replace(/\\/g, '#'); // e.g. '\5FAE' --> '#5FAE' item.value = item.value.replace(/~/g, ''); const val = /[@]/.test(item.value) ? `${opts.useRealValueFilterLessVar}` : item.value; // If there is a space ` `, use ` ` to enclose it const wrapVal = val.includes(' ') ? `\`${val}\`` : `\'${val}\'`; if (opts.jsValueObjectKv) { JS_CONTENT += ` '--${item.key}': { key: '--${item.key}', value: ${wrapVal}, },\n`; } else { JS_CONTENT += ` '--${item.key}': ${wrapVal},\n`; } }); // all two `''` --> `'` const result = `${JS_HEADER}${JS_CONTENT}${JS_FOOTER}`.replace(/''/g, "'"); fs.writeFileSync(jsOutputPath, result); } console.log(' -', outputPath, '\n'); }; // // // // if (isExecOnCLI) lessVarToCssVar(); // for CIL module.exports = lessVarToCssVar;