@@ -2,6 +2,7 @@ import {readFileSync, writeFileSync} from 'fs';
2
2
import { pathToFileURL } from 'url' ;
3
3
import { relative , join , dirname } from 'path' ;
4
4
import { compileString } from 'sass' ;
5
+ import { highlightCodeBlock } from '../highlight-files/highlight-code-block' ;
5
6
6
7
/** Information extracted for a single token from the theme. */
7
8
interface ExtractedToken {
@@ -31,6 +32,16 @@ interface Token {
31
32
derivedFrom ?: string ;
32
33
}
33
34
35
+ /** Information extracted from a theme file. */
36
+ interface ThemeData {
37
+ /** Name of the theme file. */
38
+ name : string ;
39
+ /** Name of the `overrides` mixin within the file. */
40
+ overridesMixin : string ;
41
+ /** Tokens that can be used in the `overrides` mixin. */
42
+ tokens : Token [ ] ;
43
+ }
44
+
34
45
// Script that extracts the tokens from a specific Bazel target.
35
46
if ( require . main === module ) {
36
47
const [ packagePath , outputPath , ...inputFiles ] = process . argv . slice ( 2 ) ;
@@ -52,20 +63,19 @@ if (require.main === module) {
52
63
throw new Error ( `Could not find theme files in ${ packagePath } ` ) ;
53
64
}
54
65
55
- const themes : { name : string ; overridesMixin : string ; tokens : Token [ ] } [ ] = [ ] ;
66
+ const themes : ThemeData [ ] = [ ] ;
56
67
57
68
themeFiles . forEach ( theme => {
58
- const tokens = extractTokens ( theme . filePath ) ;
59
69
themes . push ( {
60
70
name : theme . mixinPrefix ,
61
71
// This can be derived from the `name` already, but we want the source
62
72
// of truth to be in this repo, instead of whatever page consumes the data.
63
73
overridesMixin : `${ theme . mixinPrefix } -overrides` ,
64
- tokens,
74
+ tokens : extractTokens ( theme . filePath ) ,
65
75
} ) ;
66
76
} ) ;
67
77
68
- writeFileSync ( outputPath , JSON . stringify ( themes ) ) ;
78
+ writeFileSync ( outputPath , JSON . stringify ( { example : getUsageExample ( themes ) , themes } ) ) ;
69
79
}
70
80
71
81
/**
@@ -137,6 +147,41 @@ function extractTokens(themePath: string): Token[] {
137
147
} ) ;
138
148
}
139
149
150
+ /**
151
+ * Generates a highlighted code snippet that illustrates how an overrides mixin can be used.
152
+ * @param themes Themes that were extracted from a specific entrypoint. One of these themes will
153
+ * be used as an example.
154
+ */
155
+ function getUsageExample ( themes : ThemeData [ ] ) : string | null {
156
+ const mixin = themes . find ( theme => theme . tokens . length > 0 ) ;
157
+
158
+ if ( ! mixin ) {
159
+ return null ;
160
+ }
161
+
162
+ // Pick out a couple of color tokens to show as examples.
163
+ const firstToken = mixin . tokens . find ( token => token . type === 'color' ) ;
164
+ const secondToken = mixin . tokens . find ( token => token . type === 'color' && token !== firstToken ) ;
165
+
166
+ if ( ! firstToken ) {
167
+ return null ;
168
+ }
169
+
170
+ const lines = [
171
+ `@use '@angular/material' as mat;` ,
172
+ `` ,
173
+ `// Customize the entire app. Change :root to your selector if you want to scope the styles.` ,
174
+ `:root {` ,
175
+ ` @include mat.${ mixin . overridesMixin } ((` ,
176
+ ` ${ firstToken . overridesName } : orange,` ,
177
+ ...( secondToken ? [ ` ${ secondToken . overridesName } : red,` ] : [ ] ) ,
178
+ ` ));` ,
179
+ `}` ,
180
+ ] ;
181
+
182
+ return highlightCodeBlock ( lines . join ( '\n' ) , 'scss' ) ;
183
+ }
184
+
140
185
/**
141
186
* Generates the code that can be added around a theme file in order to extract its tokens.
142
187
* @param srcPath Absolute path to the source root.
0 commit comments