const {execSync} = require('child_process'); const {join} = require('path'); const { moveSync, mkdirpSync, readdirSync, readFileSync, removeSync, writeFileSync } = require('fs-extra'); const {create} = require('usercss-creator'); if (!process.env.STYLE_ENV) { throw new Error('Environment variable STYLE_ENV is not set.'); } const tempPath = join(__dirname, 'temp'); const logMeta = process.env.STYLE_ENV === 'dev' ? '[build]'.padEnd(10) : '[build] '; // If we're in prod then clear the temp folder to avoid unwanted files going into `css` if (process.env.STYLE_ENV === 'prod') { console.log(logMeta + 'building for production, see `css/` for output'); removeSync(tempPath); } console.log(`${logMeta}reading \`${join(__dirname, 'source')}\` files`); let cssFiles = readdirSync(join(__dirname, 'source')); // Generate all the SCSS using the CLI console.log(logMeta + 'generating SASS/SCSS -> CSS'); const outputStyle = 'expanded'; mkdirpSync('temp/'); for (const cssFile of cssFiles) { execSync( `yarn sass --no-source-map --style ${outputStyle} source/${cssFile}/${cssFile}.s* ${tempPath}/${cssFile}.css` ); console.log(`${logMeta}✔ ${cssFile}`); } console.log(`${logMeta}reading \`${tempPath}\` files`); cssFiles = readdirSync(tempPath); console.log(logMeta + 'generating CSS -> UserCSS'); for (const cssFile of cssFiles) { // Only generate non-usercss files if (cssFile.endsWith('.user.css')) { continue; } const cssPath = join(tempPath, cssFile); // This uses the css file's name to resolve the appropriate `package.json` // All CSS files have the same name as their directory const packagePath = join( __dirname, 'source', cssFile.slice(0, cssFile.indexOf('.')), 'package.json' ); const {usercss} = JSON.parse(readFileSync(packagePath, 'UTF8')); // We don't specify an output path because we just want it generated next to the regular CSS file create(cssPath, usercss); } cssFiles = readdirSync(tempPath); // Add `@-moz-document domain(...)` to all the `.user.css` files for (const cssFile of cssFiles) { if (!cssFile.endsWith('.user.css')) { continue; } const cssPath = join(tempPath, cssFile); const packagePath = join( __dirname, 'source', cssFile.slice(0, cssFile.indexOf('.')), 'package.json' ); const {usercss} = JSON.parse(readFileSync(packagePath, 'UTF8')); let css = readFileSync(cssPath, 'UTF8'); const usercssIndex = css.indexOf('==/UserStyle== */'); const usercssLength = '==/UserStyle== */'.length; css = css.slice(0, Math.max(0, usercssIndex + usercssLength)) + `\n@-moz-document domain("${usercss.namespace}") {\n` + css.slice(usercssIndex + usercssLength + 1, css.length) + '}\n'; writeFileSync(cssPath, css); console.log(`${logMeta}✔ ${cssFile} v${usercss.version}`); } // If we're in prod, we now wanna move all the files into `css` if (process.env.STYLE_ENV === 'prod') { cssFiles = readdirSync(tempPath); console.log(`${logMeta}moving ${cssFiles.length} generated files`); for (const cssFile of cssFiles) { const cssPath = join(tempPath, cssFile); const prodPath = join(__dirname, 'css'); const dirPath = join( prodPath, cssFile.slice(0, Math.max(0, cssFile.indexOf('.'))) ); // `mkdir -p ` to create any directories that don't exist yet mkdirpSync(dirPath); moveSync(cssPath, join(dirPath, cssFile), {overwrite: true}); } removeSync(tempPath); } console.log(logMeta + 'finished 😁');