UNPKG

saepequia

Version:

A simple, maximally extensible, dependency minimized framework for building modern Ethereum dApps

167 lines (143 loc) 4.31 kB
/** * This file contains a CLI for Linaria. */ import path from 'path'; import fs from 'fs'; import normalize from 'normalize-path'; import mkdirp from 'mkdirp'; import glob from 'glob'; import yargs from 'yargs'; import transform from './transform'; const { argv } = yargs .usage('Usage: $0 [options] <files ...>') .option('config', { alias: 'c', type: 'string', description: 'Path to a config file', requiresArg: true, }) .option('out-dir', { alias: 'o', type: 'string', description: 'Output directory for the extracted CSS files', demandOption: true, requiresArg: true, }) .option('source-maps', { alias: 's', type: 'boolean', description: 'Generate source maps for the CSS files', default: false, }) .option('source-root', { alias: 'r', type: 'string', description: 'Directory containing the source JS files', requiresArg: true, }) .option('insert-css-requires', { alias: 'i', type: 'string', description: 'Directory containing JS files to insert require statements for the CSS files', requiresArg: true, }) .implies('insert-css-requires', 'source-root') .option('ignore', { alias: 'x', type: 'string', description: 'Pattern of files to ignore. Be sure to provide a string', requiresArg: true, }) .alias('help', 'h') .alias('version', 'v') .strict(); processFiles(argv._, { outDir: argv['out-dir'], sourceMaps: argv['source-maps'], sourceRoot: argv['source-root'], insertCssRequires: argv['insert-css-requires'], configFile: argv.config, ignore: argv.ignore, }); type Options = { outDir: string; sourceMaps?: boolean; sourceRoot?: string; insertCssRequires?: string; configFile?: string; ignore?: string; }; function processFiles(files: string[], options: Options) { let count = 0; const resolvedFiles = files.reduce( (acc, pattern) => [ ...acc, ...glob.sync(pattern, { absolute: true, ignore: options.ignore }), ], [] as string[] ); resolvedFiles.forEach((filename) => { const outputFilename = resolveOutputFilename(filename, options.outDir); const { cssText, sourceMap, cssSourceMapText } = transform( fs.readFileSync(filename).toString(), { filename, outputFilename, pluginOptions: { configFile: options.configFile, }, } ); if (cssText) { mkdirp.sync(path.dirname(outputFilename)); const cssContent = options.sourceMaps && sourceMap ? `${cssText}\n/*# sourceMappingURL=${outputFilename}.map */` : cssText; fs.writeFileSync(outputFilename, cssContent); if ( options.sourceMaps && sourceMap && typeof cssSourceMapText !== 'undefined' ) { fs.writeFileSync(`${outputFilename}.map`, cssSourceMapText); } if (options.insertCssRequires && options.sourceRoot) { const inputFilename = path.resolve( options.insertCssRequires, path.relative(options.sourceRoot, filename) ); const normalizedInputFilename = resolveRequireInsertionFilename( inputFilename ); const relativePath = normalize( path.relative(path.dirname(inputFilename), outputFilename) ); const requireStatement = `\nrequire('${ relativePath.startsWith('.') ? relativePath : `./${relativePath}` }');`; const inputContent = fs.readFileSync(normalizedInputFilename, 'utf-8'); if (!inputContent.trim().endsWith(requireStatement)) { fs.writeFileSync( normalizedInputFilename, `${inputContent}\n${requireStatement}\n` ); } } count++; } }); // eslint-disable-next-line no-console console.log(`Successfully extracted ${count} CSS files.`); } function resolveRequireInsertionFilename(filename: string) { return filename.replace(/\.tsx?/, '.js'); } function resolveOutputFilename(filename: string, outDir: string) { const folderStructure = path.relative(process.cwd(), path.dirname(filename)); const outputBasename = path .basename(filename) .replace(path.extname(filename), '.css'); return path.join(outDir, folderStructure, outputBasename); }