Skip to content

Commit

Permalink
feat: move design tokens CLI commands to paragon CLI (#2609)
Browse files Browse the repository at this point in the history
* feat: move cli design tokens to paragon cli

* feat: update paths for build-tokens.js

* feat: added descriptions for CLI commands

* refactor: removed commander implementation

* refactor: added build-scss process status

* feat: added ora compilation status

* refactor: code refactoring

* feat: added help description for single command

* refactor: after review

* refactor: refactoring after review

* chore: update docs and cli params parsing

---------

Co-authored-by: monteri <lansevermore>
Co-authored-by: PKulkoRaccoonGang <[email protected]>
Co-authored-by: Viktor Rusakov <[email protected]>
  • Loading branch information
3 people committed Aug 1, 2024
1 parent 703a16e commit 462ee16
Show file tree
Hide file tree
Showing 11 changed files with 474 additions and 234 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ build:
rm -rf dist/**/__snapshots__
rm -rf dist/__mocks__
rm -rf dist/setupTest.js
node build-scss.js
./bin/paragon-scripts.js build-scss

export TRANSIFEX_RESOURCE = paragon
transifex_langs = "ar,ca,es_419,fr,he,id,ko_KR,pl,pt_BR,ru,th,uk,zh_CN,es_AR,es_ES,pt_PT,tr_TR,it_IT"
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ The Paragon CLI (Command Line Interface) is a tool that provides various utility

### Available Commands

- `paragon install-theme [theme]`: Installs the specific @edx/brand package.
- `paragon install-theme [theme]`: Installs the specific [brand package](https://github.com/openedx/brand-openedx).
- `paragon build-tokens`: Build Paragon's design tokens.
- `paragon replace-variables`: Replace SCSS variables usages or definitions to CSS variables and vice versa in `.scss` files.
- `paragon build-scss`: Compile Paragon's core and themes SCSS into CSS.

Use `paragon help` to see more information.

Expand Down
135 changes: 125 additions & 10 deletions bin/paragon-scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
const chalk = require('chalk');
const themeCommand = require('../lib/install-theme');
const helpCommand = require('../lib/help');

const HELP_COMMAND = 'help';
const buildTokensCommand = require('../lib/build-tokens');
const replaceVariablesCommand = require('../lib/replace-variables');
const buildScssCommand = require('../lib/build-scss');

const COMMANDS = {
/**
Expand All @@ -25,6 +26,9 @@ const COMMANDS = {
* {
* name: '--optionName',
* description: 'optionDescription',
* choices: 'optionChoices',
* defaultValue: 'optionDefaultValue',
* required: true/false,
* },
* ...
* ],
Expand All @@ -43,14 +47,130 @@ const COMMANDS = {
},
],
},
'build-tokens': {
executor: buildTokensCommand,
description: 'CLI to build Paragon design tokens.',
options: [
{
name: '-s, --source',
description: 'Specify the source directory for design tokens.',
defaultValue: '\'\'',
},
{
name: '-b, --build-dir',
description: 'Specify the build directory for the generated tokens.',
defaultValue: './build/',
},
{
name: '--source-tokens-only',
description: 'Include only source design tokens in the build.',
defaultValue: false,
},
{
name: '-t, --themes',
description: 'Specify themes to include in the token build.',
defaultValue: 'light',
},
],
},
'replace-variables': {
executor: replaceVariablesCommand,
description: 'CLI to replace SCSS variables usages or definitions to CSS variables and vice versa in .scss files.',
parameters: [
{
name: '-p, --filePath',
description: 'Path to the file or directory where to replace variables.',
defaultValue: '\'\'',
},
],
options: [
{
name: '-s, --source',
description: 'Type of replacement: usage or definition. If set to "definition" the command will only update SCSS variables definitions with CSS variables, if set to "usage" - all occurrences of SCSS variables will we replaced',
defaultValue: '\'\'',
},
{
name: '-t, --replacementType',
description: 'Type of replacement: usage or definition. If set to "definition" the command will only update SCSS variables definitions with CSS variables, if set to "usage" - all occurrences of SCSS variables will we replaced',
choices: '[usage|definition]',
defaultValue: 'definition',
},
{
name: '-d, --direction',
description: 'Map direction: css-to-scss or scss-to-css, if replacement type parameter is set to "definition" this has no effect.',
choices: '[scss-to-css|css-to-scss]',
defaultValue: 'scss-to-css',
},
],
},
'build-scss': {
executor: buildScssCommand,
description: 'CLI to compile Paragon\'s core and themes SCSS into CSS.',
options: [
{
name: '--corePath',
description: 'Path to the theme\'s core SCSS file, defaults to Paragon\'s core.scss.',
defaultValue: 'styles/scss/core/core.scss',
},
{
name: '--themesPath',
description: `Path to the directory that contains themes' files. Expects directory to have following structure:
themes/
light/
│ ├─ index.css
│ ├─ other_css_files
dark/
│ ├─ index.css
│ ├─ other_css_files
some_other_custom_theme/
│ ├─ index.css
│ ├─ other_css_files
...
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.
`,
defaultValue: 'styles/css/themes',
},
{
name: '--outDir',
description: 'Specifies directory where to out resulting CSS files.',
defaultValue: './dist',
},
{
name: '--defaultThemeVariants',
description: `Specifies default theme variants. Defaults to a single 'light' theme variant.
You can provide multiple default theme variants by passing multiple values, for
example: \`--defaultThemeVariants light dark\`
`,
defaultValue: 'light',
},
],
},
help: {
executor: helpCommand,
executor: (args) => helpCommand(COMMANDS, args),
parameters: [
{
name: 'command',
description: 'Specifies command name.',
defaultValue: '\'\'',
choices: '[install-theme|build-tokens|replace-variables|build-scss]',
required: false,
},
],
description: 'Displays help for available commands.',
},
};

/**
* Executes a Paragon CLI command based on the provided command-line arguments.
*
* @async
* @function executeParagonCommand
*/
(async () => {
const [command] = process.argv.slice(2);
const [command, ...commandArgs] = process.argv.slice(2);
const executor = COMMANDS[command];

if (!executor) {
Expand All @@ -59,13 +179,8 @@ const COMMANDS = {
return;
}

if (command === HELP_COMMAND) {
helpCommand(COMMANDS);
return;
}

try {
await executor.executor();
await executor.executor(commandArgs);
} catch (error) {
// eslint-disable-next-line no-console
console.error(chalk.red.bold('An error occurred:', error.message));
Expand Down
127 changes: 52 additions & 75 deletions build-scss.js → lib/build-scss.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env node
const fs = require('fs');
const sass = require('sass');
const postCSS = require('postcss');
Expand All @@ -8,7 +7,10 @@ const postCSSMinify = require('postcss-minify');
const combineSelectors = require('postcss-combine-duplicated-selectors');
const { pathToFileURL } = require('url');
const path = require('path');
const { program, Option } = require('commander');
const minimist = require('minimist');
const chalk = require('chalk');
const ora = require('ora');
const { capitalize } = require('./utils');

const paragonThemeOutputFilename = 'theme-urls.json';

Expand Down Expand Up @@ -92,17 +94,19 @@ const compileAndWriteStyleSheets = ({
},
}],
});

const commonPostCssPlugins = [
postCSSImport(),
postCSSCustomMedia({ preserve: true }),
combineSelectors({ removeDuplicatedProperties: true }),
];

const postCSSCompilation = ora(`Compilation for ${capitalize(name)} stylesheet...`).start();
postCSS(commonPostCssPlugins)
.process(compiledStyleSheet.css, { from: stylesPath, map: false })
.then((result) => {
postCSSCompilation.succeed(`Successfully compiled ${capitalize(name)} theme stylesheet`);
fs.writeFileSync(`${outDir}/${name}.css`, result.css);

postCSS([postCSSMinify()])
.process(result.css, { from: `${name}.css`, map: { inline: false } })
.then((minifiedResult) => {
Expand All @@ -129,83 +133,56 @@ const compileAndWriteStyleSheets = ({
isDefaultThemeVariant,
});
}

fs.writeFileSync(`${outDir}/${paragonThemeOutputFilename}`, `${JSON.stringify(paragonThemeOutput, null, 2)}\n`);
})
.then(() => {
ora().succeed(chalk.underline.bold.green(`Successfully built stylesheet for ${capitalize(name)} theme!\n`));
})
.catch((error) => {
ora().fail(chalk.bold(`Failed to build stylesheets for ${capitalize(name)}: ${error.message}`));
});
};

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.',
),
)
.addOption(
new Option(
'--themesPath <themesPath>',
`Path to the directory that contains themes' files. Expects directory to have following structure:
themes/
light/
│ ├─ index.css
│ ├─ other_css_files
dark/
│ ├─ index.css
│ ├─ other_css_files
some_other_custom_theme/
│ ├─ index.css
│ ├─ other_css_files
...
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.',
),
)
.addOption(
new Option(
'--defaultThemeVariants <defaultThemeVariants...>',
`Specifies default theme variants. Defaults to a single 'light' theme variant.
You can provide multiple default theme variants by passing multiple values, for
example: \`--defaultThemeVariants light dark\`
`,
),
);

program.parse(process.argv);
/**
* Builds SCSS stylesheets based on the provided command arguments.
*
* @param {Array<string>} commandArgs - Command line arguments for building SCSS stylesheets.
*/
function buildScssCommand(commandArgs) {
const defaultArgs = {
corePath: path.resolve(process.cwd(), 'styles/scss/core/core.scss'),
themesPath: path.resolve(process.cwd(), 'styles/css/themes'),
outDir: './dist',
defaultThemeVariants: 'light',
};

const options = program.opts();
const {
corePath = path.resolve(__dirname, 'styles/scss/core/core.scss'),
themesPath = path.resolve(__dirname, 'styles/css/themes'),
outDir = './dist',
defaultThemeVariants = ['light'],
} = options;
const {
corePath,
themesPath,
outDir,
defaultThemeVariants,
} = minimist(commandArgs, { default: defaultArgs });

// Core CSS
compileAndWriteStyleSheets({
name: 'core',
stylesPath: corePath,
outDir,
});
// Core CSS
compileAndWriteStyleSheets({
name: 'core',
stylesPath: corePath,
outDir,
});

// Theme Variants CSS
fs.readdirSync(themesPath, { withFileTypes: true })
.filter((item) => item.isDirectory())
.forEach((themeDir) => {
compileAndWriteStyleSheets({
name: themeDir.name,
stylesPath: `${themesPath}/${themeDir.name}/index.css`,
outDir,
isThemeVariant: true,
isDefaultThemeVariant: defaultThemeVariants.includes(themeDir.name),
// Theme Variants CSS
fs.readdirSync(themesPath, { withFileTypes: true })
.filter((item) => item.isDirectory())
.forEach((themeDir) => {
compileAndWriteStyleSheets({
name: themeDir.name,
stylesPath: `${themesPath}/${themeDir.name}/index.css`,
outDir,
isThemeVariant: true,
isDefaultThemeVariant: defaultThemeVariants.includes(themeDir.name),
});
});
});
}

module.exports = buildScssCommand;
Loading

0 comments on commit 462ee16

Please sign in to comment.