Skip to content

Commit

Permalink
feat: generate paragon-theme.json during npm run build with themeUrls (
Browse files Browse the repository at this point in the history
…openedx#2333)

* feat: generate paragon.config.json during npm run build with themeUrls
* fix: rename to paragon-theme.json
* chore: rename paragonConfig
  • Loading branch information
adamstankiewicz authored and PKulkoRaccoonGang committed Aug 18, 2023
1 parent 354cc97 commit f55e9bc
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 27 deletions.
1 change: 0 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ node_modules/
www/
icons/
dependent-usage-analyzer/
build-scss.js
component-generator/
example/
128 changes: 102 additions & 26 deletions build-scss.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,119 @@ const { pathToFileURL } = require('url');
const path = require('path');
const { program, Option } = require('commander');

const paragonThemeOutputFilename = 'paragon-theme.json';

/**
* Updates `paragonThemeOutput` object with appropriate name and URLs.
*
* @param {object} args
* @param {object} args.paragonThemeOutput Object containing the `themeUrls` pointing
* to the core and theme variant CSS files.
* @param {string} args.name Name of the theme variant.
* @param {boolean} args.isThemeVariant Indicates whether the stylesheet is a theme variant.
*
* @returns Updated paragonThemeOutput object.
*/
const updateParagonThemeOutput = ({
paragonThemeOutput,
name,
isThemeVariant,
}) => {
if (isThemeVariant) {
paragonThemeOutput.themeUrls.variants = {
...paragonThemeOutput.themeUrls.variants,
[name]: {
default: `./${name}.css`,
minified: `./${name}.min.css`,
},
};
} else {
paragonThemeOutput.themeUrls[name] = {
default: `./${name}.css`,
minified: `./${name}.min.css`,
};
}
return paragonThemeOutput;
};

/**
* Compiles SCSS file with sass and transforms resulting file with PostCSS:
* 1. Resulting CSS file
* 2. Map file
* 3. Minified version of resulting CSS file
*
* @param {string} name - base name of the resulting files
* @param {string} path - path to the SCSS stylesheet
* @param {string} stylesPath - path to the stylesheet to be compiled
* @param {string} outDir - indicates where to output compiled files
* @param {boolean} isThemeVariant - indicates whether the stylesheet is a theme variant
*/
const compileAndWriteStyleSheets = (name, path, outDir) => {
const compiledStyleSheet = sass.compile(path, {
const compileAndWriteStyleSheets = ({
name,
stylesPath,
outDir,
isThemeVariant = false,
}) => {
const compiledStyleSheet = sass.compile(stylesPath, {
importers: [{
// An importer that redirects relative URLs starting with '~' to 'node_modules'.
findFileUrl(url) {
if (!url.startsWith('~')) {
return null;
}
return new URL(url.substring(1), `${pathToFileURL('node_modules')}/node_modules`)
}
}]
return new URL(url.substring(1), `${pathToFileURL('node_modules')}/node_modules`);
},
}],
});
const commonPostCssPlugins = [
postCSSCustomMedia({ preserve: true }),
postCSSImport(),
combineSelectors({ removeDuplicatedProperties: true }),
];

postCSS([
postCSSCustomMedia({ preserve: true }),
postCSSImport(),
combineSelectors({ removeDuplicatedProperties: true })])
.process(compiledStyleSheet.css, { from: path, map: { inline: false } })
postCSS(commonPostCssPlugins)
.process(compiledStyleSheet.css, { from: stylesPath, map: { inline: false } })
.then(result => {
fs.writeFileSync(`${outDir}/${name}.css`, result.css);
fs.writeFileSync(`${outDir}/${name}.css.map`, result.map.toString());

const hasExistingParagonThemeOutput = fs.existsSync(`${outDir}/${paragonThemeOutputFilename}`);
let paragonThemeOutput;
if (!hasExistingParagonThemeOutput) {
const initialConfigOutput = { themeUrls: {} };
paragonThemeOutput = updateParagonThemeOutput({
paragonThemeOutput: initialConfigOutput,
name,
isThemeVariant,
});
} else {
const existingParagonThemeOutput = JSON.parse(fs.readFileSync(`${outDir}/${paragonThemeOutputFilename}`, 'utf8'));
paragonThemeOutput = updateParagonThemeOutput({
paragonThemeOutput: existingParagonThemeOutput,
name,
isThemeVariant,
});
}
fs.writeFileSync(`${outDir}/${paragonThemeOutputFilename}`, `${JSON.stringify(paragonThemeOutput, null, 2)}\n`);
});

postCSS([
postCSSCustomMedia({ preserve: true }),
postCSSImport(),
postCSSMinify(),
combineSelectors({ removeDuplicatedProperties: true })])
.process(compiledStyleSheet.css, { from: path })
.then(result => fs.writeFileSync(`${outDir}/${name}.min.css`, result.css));
}
...commonPostCssPlugins,
postCSSMinify(),
])
.process(compiledStyleSheet.css, { from: stylesPath, map: { inline: false } })
.then(result => {
fs.writeFileSync(`${outDir}/${name}.min.css`, result.css);
});
};

program
.version('0.0.1')
.description('CLI to compile Paragon\'s core and themes\' SCSS into CSS.')
.addOption(
new Option(
'--corePath <corePath>',
'Path to the theme\'s core SCSS file, defaults to Paragon\'s core.scss.')
'Path to the theme\'s core SCSS file, defaults to Paragon\'s core.scss.',
),
)
.addOption(
new Option(
Expand All @@ -79,24 +143,36 @@ program
where index.css has imported all other CSS files in the theme's subdirectory. The script will output
light.css, dark.css and some_other_custom_theme.css files (together with maps and minified versions).
You can provide any amount of themes. Default to paragon's themes.
`
))
`,
),
)
.addOption(
new Option(
'--outDir <outDir>',
'Specifies directory where to out resulting CSS files.'
)
'Specifies directory where to out resulting CSS files.',
),
)
.action(async (options) => {
const {
corePath = path.resolve(__dirname, 'styles/scss/core/core.scss'),
themesPath = path.resolve(__dirname, 'styles/css/themes'),
outDir = './dist'
outDir = './dist',
} = options;
compileAndWriteStyleSheets('core', corePath, outDir);
compileAndWriteStyleSheets({
name: 'core',
stylesPath: corePath,
outDir,
});
fs.readdirSync(themesPath, { withFileTypes: true })
.filter((item) => item.isDirectory())
.forEach((themeDir) => compileAndWriteStyleSheets(themeDir.name, `${themesPath}/${themeDir.name}/index.css`, outDir))
.forEach((themeDir) => {
compileAndWriteStyleSheets({
name: themeDir.name,
stylesPath: `${themesPath}/${themeDir.name}/index.css`,
outDir,
isThemeVariant: true,
});
});
});

program.parse(process.argv);

0 comments on commit f55e9bc

Please sign in to comment.