From c49dcf1a584282575f13166d2f718935913f3d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Wed, 20 Mar 2019 15:32:52 +0100 Subject: [PATCH 1/3] prettify scss compilation script --- scripts/compile-scss.js | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/scripts/compile-scss.js b/scripts/compile-scss.js index b46ce43bc60..5b55277893a 100755 --- a/scripts/compile-scss.js +++ b/scripts/compile-scss.js @@ -18,7 +18,7 @@ const postcssConfigurationWithMinification = { ...postcssConfiguration, plugins: [ ...postcssConfiguration.plugins, - require('cssnano')({ preset: 'default' }) + require('cssnano')({ preset: 'default' }), ], }; @@ -51,14 +51,25 @@ async function compileScssFiles(sourcePattern, destinationDirectory) { .join(', ')}` ); } catch (error) { - console.log(chalk`{red ✗} Failed to compile {gray ${inputFilename}} with ${error.stack}`); + console.log( + chalk`{red ✗} Failed to compile {gray ${inputFilename}} with ${ + error.stack + }` + ); } }) ); } -async function compileScssFile(inputFilename, outputCssFilename, outputVarsFilename) { - const outputCssMinifiedFilename = outputCssFilename.replace(/\.css$/, '.min.css'); +async function compileScssFile( + inputFilename, + outputCssFilename, + outputVarsFilename +) { + const outputCssMinifiedFilename = outputCssFilename.replace( + /\.css$/, + '.min.css' + ); const { css: renderedCss, vars: extractedVars } = await sassExtract.render( { @@ -70,12 +81,17 @@ async function compileScssFile(inputFilename, outputCssFilename, outputVarsFilen } ); - const { css: postprocessedCss } = await postcss(postcssConfiguration).process(renderedCss, { - from: outputCssFilename, - to: outputCssFilename, - }); + const { css: postprocessedCss } = await postcss(postcssConfiguration).process( + renderedCss, + { + from: outputCssFilename, + to: outputCssFilename, + } + ); - const { css: postprocessedMinifiedCss } = await postcss(postcssConfigurationWithMinification).process(renderedCss, { + const { css: postprocessedMinifiedCss } = await postcss( + postcssConfigurationWithMinification + ).process(renderedCss, { from: outputCssFilename, to: outputCssMinifiedFilename, }); From b2812f52f4972d186863407b9b778f252beb1547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Wed, 20 Mar 2019 19:40:56 +0100 Subject: [PATCH 2/3] Emit TS types for variables extracted from sass --- package.json | 2 +- scripts/compile-scss.js | 40 ++++++++++++-- scripts/derive-sass-variable-types.js | 75 +++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 scripts/derive-sass-variable-types.js diff --git a/package.json b/package.json index cb77c589009..d7444155a9d 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "test-docker": "docker pull $npm_package_docker_image && docker run --rm -i -e GIT_COMMITTER_NAME=test -e GIT_COMMITTER_EMAIL=test --user=$(id -u):$(id -g) -e HOME=/tmp -v $(pwd):/app -w /app $npm_package_docker_image bash -c 'npm config set spin false && /opt/yarn*/bin/yarn && npm run test && npm run build'", "sync-docs": "node ./scripts/docs-sync.js", "build-docs": "webpack --config=src-docs/webpack.config.js", - "build": "yarn extract-i18n-strings && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && node ./scripts/compile-scss.js", + "build": "yarn extract-i18n-strings && node ./scripts/compile-clean.js && node ./scripts/compile-eui.js && node ./scripts/compile-scss.js $npm_package_name", "extract-i18n-strings": "node ./scripts/babel/fetch-i18n-strings", "lint": "yarn lint-es && yarn lint-ts && yarn lint-sass && yarn lint-framer", "lint-fix": "yarn lint-es-fix && yarn lint-ts-fix", diff --git a/scripts/compile-scss.js b/scripts/compile-scss.js index 5b55277893a..c66b2ea2bd7 100755 --- a/scripts/compile-scss.js +++ b/scripts/compile-scss.js @@ -6,6 +6,7 @@ const globModule = require('glob'); const chalk = require('chalk'); const postcss = require('postcss'); const sassExtract = require('sass-extract'); +const { deriveSassVariableTypes } = require('./derive-sass-variable-types'); const sassExtractJsPlugin = require('./sass-extract-js-plugin'); const postcssConfiguration = require('../src-docs/postcss.config.js'); @@ -22,7 +23,11 @@ const postcssConfigurationWithMinification = { ], }; -async function compileScssFiles(sourcePattern, destinationDirectory) { +async function compileScssFiles( + sourcePattern, + destinationDirectory, + packageName +) { try { await mkdir(destinationDirectory); } catch (err) { @@ -42,7 +47,9 @@ async function compileScssFiles(sourcePattern, destinationDirectory) { const outputFilenames = await compileScssFile( inputFilename, path.join(destinationDirectory, `eui_${name}.css`), - path.join(destinationDirectory, `eui_${name}.json`) + path.join(destinationDirectory, `eui_${name}.json`), + path.join(destinationDirectory, `eui_${name}.json.d.ts`), + packageName ); console.log( @@ -64,7 +71,9 @@ async function compileScssFiles(sourcePattern, destinationDirectory) { async function compileScssFile( inputFilename, outputCssFilename, - outputVarsFilename + outputVarsFilename, + outputVarTypesFilename, + packageName ) { const outputCssMinifiedFilename = outputCssFilename.replace( /\.css$/, @@ -81,6 +90,12 @@ async function compileScssFile( } ); + const extractedVarTypes = await deriveSassVariableTypes( + extractedVars, + `${packageName}/${outputVarsFilename}`, + outputVarTypesFilename + ); + const { css: postprocessedCss } = await postcss(postcssConfiguration).process( renderedCss, { @@ -100,9 +115,24 @@ async function compileScssFile( writeFile(outputCssFilename, postprocessedCss), writeFile(outputCssMinifiedFilename, postprocessedMinifiedCss), writeFile(outputVarsFilename, JSON.stringify(extractedVars, undefined, 2)), + writeFile(outputVarTypesFilename, extractedVarTypes), ]); - return [outputCssFilename, outputVarsFilename]; + return [ + outputCssFilename, + outputCssMinifiedFilename, + outputVarsFilename, + outputVarTypesFilename, + ]; } -compileScssFiles(path.join('src', 'theme_*.scss'), 'dist'); +if (require.main === module) { + const [nodeBin, scriptName, euiPackageName] = process.argv; + + if (process.argv.length < 3) { + console.log(chalk`{bold Usage:} ${nodeBin} ${scriptName} eui-package-name`); + process.exit(1); + } + + compileScssFiles(path.join('src', 'theme_*.scss'), 'dist', euiPackageName); +} diff --git a/scripts/derive-sass-variable-types.js b/scripts/derive-sass-variable-types.js new file mode 100644 index 00000000000..f910421f62d --- /dev/null +++ b/scripts/derive-sass-variable-types.js @@ -0,0 +1,75 @@ +const ts = require('typescript'); +const prettier = require('prettier'); + +async function deriveSassVariableTypes( + extractedVars, + extractedVarsModuleName, + extractedVarTypesFilename +) { + const extractedVarsModuleDeclaration = ts.createModuleDeclaration( + undefined, + [ts.createModifier(ts.SyntaxKind.DeclareKeyword)], + ts.createStringLiteral(extractedVarsModuleName), + ts.createModuleBlock([ + ts.createVariableStatement( + undefined, + ts.createVariableDeclarationList( + [ + ts.createVariableDeclaration( + 'sassVariables', + deriveValueType(extractedVars) + ), + ], + ts.NodeFlags.Const + ) + ), + ts.createExportAssignment( + undefined, + undefined, + undefined, + ts.createIdentifier('sassVariables') + ), + ]), + ts.NodeFlags.None + ); + + const moduleSource = ts + .createPrinter({ newLine: ts.NewLineKind.LineFeed }) + .printNode( + ts.EmitHint.Unspecified, + extractedVarsModuleDeclaration, + ts.createSourceFile(extractedVarTypesFilename, '', ts.ScriptTarget.Latest) + ); + + const prettierOptions = await prettier.resolveConfig(extractedVarTypesFilename); + const prettifiedModuleSource = prettier.format(moduleSource, prettierOptions); + + return prettifiedModuleSource; +} + +function deriveValueType(extractedValue) { + switch (typeof extractedValue) { + case 'object': + return ts.createTypeLiteralNode( + Object.keys(extractedValue).map(key => + ts.createPropertySignature( + undefined, + ts.createStringLiteral(key), + undefined, + deriveValueType(extractedValue[key]), + undefined + ) + ) + ); + case 'string': + return ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword); + case 'number': + return ts.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword); + default: + return ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + } +} + +module.exports = { + deriveSassVariableTypes, +}; From 22686c9b0dcd288fb07ad8ea68da1b7eeebd750f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Wed, 20 Mar 2019 20:10:51 +0100 Subject: [PATCH 3/3] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a80b9387d4d..f9cf859669f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Added documentation entry in `EuiPagination` for `activePage` prop. ([#1740](https://github.com/elastic/eui/pull/1740)) - Changed `EuiButton` to use "m" as it's default `size` prop ([#1742](https://github.com/elastic/eui/pull/1742)) +- Enhanced the build process to emit TypeScript types for the variables extracted from the themes ([#1750](https://github.com/elastic/eui/pull/1750)) ## [`9.4.2`](https://github.com/elastic/eui/tree/v9.4.2)