From 70a1d7f17155c30bd27a699cdc64998cd10cd24c Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 4 Nov 2024 10:52:13 +0100 Subject: [PATCH] build: generate styling example during the build Currently the example in the styling pages on the docs site is generated at runtime which doesn't allow us to highlight it as code correctly. These changes move the generation of the example into the main repo and add syntax highlighting. --- tools/extract-tokens/BUILD.bazel | 2 + tools/extract-tokens/extract-tokens.ts | 53 ++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/tools/extract-tokens/BUILD.bazel b/tools/extract-tokens/BUILD.bazel index ab58b0f7c342..1877ba74e2b3 100644 --- a/tools/extract-tokens/BUILD.bazel +++ b/tools/extract-tokens/BUILD.bazel @@ -10,6 +10,7 @@ ts_library( devmode_module = "commonjs", tsconfig = ":tsconfig.json", deps = [ + "//tools/highlight-files:sources", "@npm//@types/node", "@npm//sass", ], @@ -19,6 +20,7 @@ nodejs_binary( name = "extract-tokens", data = [ ":extract_tokens_lib", + "@npm//highlight.js", "@npm//sass", ], entry_point = ":extract-tokens.ts", diff --git a/tools/extract-tokens/extract-tokens.ts b/tools/extract-tokens/extract-tokens.ts index 11acd6b831dc..fdbcb471db60 100644 --- a/tools/extract-tokens/extract-tokens.ts +++ b/tools/extract-tokens/extract-tokens.ts @@ -2,6 +2,7 @@ import {readFileSync, writeFileSync} from 'fs'; import {pathToFileURL} from 'url'; import {relative, join, dirname} from 'path'; import {compileString} from 'sass'; +import {highlightCodeBlock} from '../highlight-files/highlight-code-block'; /** Information extracted for a single token from the theme. */ interface ExtractedToken { @@ -31,6 +32,16 @@ interface Token { derivedFrom?: string; } +/** Information extracted from a theme file. */ +interface ThemeData { + /** Name of the theme file. */ + name: string; + /** Name of the `overrides` mixin within the file. */ + overridesMixin: string; + /** Tokens that can be used in the `overrides` mixin. */ + tokens: Token[]; +} + // Script that extracts the tokens from a specific Bazel target. if (require.main === module) { const [packagePath, outputPath, ...inputFiles] = process.argv.slice(2); @@ -52,20 +63,19 @@ if (require.main === module) { throw new Error(`Could not find theme files in ${packagePath}`); } - const themes: {name: string; overridesMixin: string; tokens: Token[]}[] = []; + const themes: ThemeData[] = []; themeFiles.forEach(theme => { - const tokens = extractTokens(theme.filePath); themes.push({ name: theme.mixinPrefix, // This can be derived from the `name` already, but we want the source // of truth to be in this repo, instead of whatever page consumes the data. overridesMixin: `${theme.mixinPrefix}-overrides`, - tokens, + tokens: extractTokens(theme.filePath), }); }); - writeFileSync(outputPath, JSON.stringify(themes)); + writeFileSync(outputPath, JSON.stringify({example: getUsageExample(themes), themes})); } /** @@ -137,6 +147,41 @@ function extractTokens(themePath: string): Token[] { }); } +/** + * Generates a highlighted code snippet that illustrates how an overrides mixin can be used. + * @param themes Themes that were extracted from a specific entrypoint. One of these themes will + * be used as an example. + */ +function getUsageExample(themes: ThemeData[]): string | null { + const mixin = themes.find(theme => theme.tokens.length > 0); + + if (!mixin) { + return null; + } + + // Pick out a couple of color tokens to show as examples. + const firstToken = mixin.tokens.find(token => token.type === 'color'); + const secondToken = mixin.tokens.find(token => token.type === 'color' && token !== firstToken); + + if (!firstToken) { + return null; + } + + const lines = [ + `@use '@angular/material' as mat;`, + ``, + `// Customize the entire app. Change :root to your selector if you want to scope the styles.`, + `:root {`, + ` @include mat.${mixin.overridesMixin}((`, + ` ${firstToken.overridesName}: orange,`, + ...(secondToken ? [` ${secondToken.overridesName}: red,`] : []), + ` ));`, + `}`, + ]; + + return highlightCodeBlock(lines.join('\n'), 'scss'); +} + /** * Generates the code that can be added around a theme file in order to extract its tokens. * @param srcPath Absolute path to the source root.