@digdir/designsystemet 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/build/bin/designsystemet.js +47 -0
  2. package/dist/build/src/codemods/css-var-codemod.js +36 -0
  3. package/dist/build/src/migrations/index.js +8 -0
  4. package/dist/build/src/migrations/light-dark.js +22 -0
  5. package/dist/build/src/migrations/prefix-ds.js +7 -0
  6. package/dist/build/src/migrations/tokens-v2.js +210 -0
  7. package/dist/build/src/tokens/build.js +140 -0
  8. package/dist/build/src/tokens/formatters.js +78 -0
  9. package/dist/build/src/tokens/noCase.js +30 -0
  10. package/dist/build/src/tokens/transformers.js +39 -0
  11. package/dist/build/tsconfig.tsbuildinfo +1 -0
  12. package/dist/types/bin/designsystemet.d.ts +3 -0
  13. package/dist/types/bin/designsystemet.d.ts.map +1 -0
  14. package/dist/types/src/codemods/css-var-codemod.d.ts +7 -0
  15. package/dist/types/src/codemods/css-var-codemod.d.ts.map +1 -0
  16. package/dist/types/src/migrations/index.d.ts +7 -0
  17. package/dist/types/src/migrations/index.d.ts.map +1 -0
  18. package/dist/types/src/migrations/light-dark.d.ts +3 -0
  19. package/dist/types/src/migrations/light-dark.d.ts.map +1 -0
  20. package/dist/types/src/migrations/prefix-ds.d.ts +3 -0
  21. package/dist/types/src/migrations/prefix-ds.d.ts.map +1 -0
  22. package/dist/types/src/migrations/tokens-v2.d.ts +3 -0
  23. package/dist/types/src/migrations/tokens-v2.d.ts.map +1 -0
  24. package/dist/types/src/tokens/build.d.ts +7 -0
  25. package/dist/types/src/tokens/build.d.ts.map +1 -0
  26. package/dist/types/src/tokens/formatters.d.ts +10 -0
  27. package/dist/types/src/tokens/formatters.d.ts.map +1 -0
  28. package/dist/types/src/tokens/noCase.d.ts +11 -0
  29. package/dist/types/src/tokens/noCase.d.ts.map +1 -0
  30. package/dist/types/src/tokens/transformers.d.ts +5 -0
  31. package/dist/types/src/tokens/transformers.d.ts.map +1 -0
  32. package/package.json +6 -4
  33. package/dist/bin/designsystemet.js +0 -43
  34. package/dist/chunk-3INHRMDA.js +0 -30
  35. package/dist/chunk-AFUBGWSA.js +0 -15
  36. package/dist/chunk-AH6WYHXT.js +0 -219
  37. package/dist/chunk-F6JN3G6R.js +0 -33
  38. package/dist/chunk-FSFXGZ5S.js +0 -48
  39. package/dist/chunk-HG7XELK3.js +0 -79
  40. package/dist/chunk-N6YJGJKH.js +0 -38
  41. package/dist/chunk-Q4LKHGOS.js +0 -153
  42. package/dist/chunk-XTBS6KQY.js +0 -20
  43. package/dist/src/codemods/css-var-codemod.js +0 -6
  44. package/dist/src/migrations/index.js +0 -10
  45. package/dist/src/migrations/light-dark.js +0 -7
  46. package/dist/src/migrations/prefix-ds.js +0 -7
  47. package/dist/src/migrations/tokens-v2.js +0 -7
  48. package/dist/src/tokens/build.js +0 -9
  49. package/dist/src/tokens/formatters.js +0 -8
  50. package/dist/src/tokens/noCase.js +0 -6
  51. package/dist/src/tokens/transformers.js +0 -11
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ import { Argument, program } from '@commander-js/extra-typings';
3
+ import chalk from 'chalk';
4
+ import migrations from './../src/migrations/index.js';
5
+ import { run } from './../src/tokens/build.js';
6
+ program.name('Designsystemet').description('CLI for working with Designsystemet');
7
+ program
8
+ .command('tokens')
9
+ .showHelpAfterError()
10
+ .description('run Designsystemet token builder')
11
+ .option('-t, --tokens <string>', 'Path to "design-tokens"', '../../design-tokens')
12
+ .option('-p, --preview')
13
+ .action((opts) => {
14
+ const tokens = typeof opts.tokens === 'string' ? opts.tokens : '';
15
+ console.log(`Bulding tokens in ${chalk.green(tokens)}`);
16
+ return run({ tokens });
17
+ });
18
+ program
19
+ .command('migrate')
20
+ .showHelpAfterError()
21
+ .description('run a Designsystemet migration')
22
+ .addArgument(new Argument('[migration]', 'Available migrations').choices(Object.keys(migrations)))
23
+ .option('-l --list', 'List available migrations')
24
+ .option('-g --glob <glob>', 'Glob for files upon which to apply the migration', './**/*.css')
25
+ .action((migrationKey, opts) => {
26
+ const { glob, list } = opts;
27
+ if (list) {
28
+ Object.keys(migrations).forEach((key) => {
29
+ console.log(key);
30
+ });
31
+ }
32
+ else if (migrationKey) {
33
+ const migration = migrations[migrationKey];
34
+ if (!migration) {
35
+ console.error('Migration not found!');
36
+ throw 'Aborting';
37
+ }
38
+ console.log(`Applying migration ${chalk.blue(migrationKey)} with glob: ${chalk.green(glob)}`);
39
+ migration?.(glob)
40
+ .then(() => console.log(`Migration ${chalk.blue(migrationKey)} finished`))
41
+ .catch((error) => console.log(error));
42
+ }
43
+ else {
44
+ console.log('Migrate: please specify a migration name or --list');
45
+ }
46
+ });
47
+ await program.parseAsync(process.argv);
@@ -0,0 +1,36 @@
1
+ import fs from 'fs';
2
+ import * as R from 'ramda';
3
+ import postcss from 'postcss';
4
+ import glob from 'fast-glob';
5
+ export const cssVarCodemod = async ({ dictionary, globPath = './**/*.css' }) => {
6
+ const transformPlugin = {
7
+ postcssPlugin: 'Replaces referenced CSS variables',
8
+ Declaration(decl) {
9
+ Object.keys(dictionary).forEach((key) => {
10
+ const newValue = dictionary[key];
11
+ if (R.isEmpty(newValue)) {
12
+ //console.log(`Skipping "${key}"; missing new value`);
13
+ }
14
+ if (newValue === '[delete]') {
15
+ //console.log(`Found delete token "${key}"`);
16
+ }
17
+ if (decl.value.includes(key) && !R.isEmpty(newValue)) {
18
+ decl.value = decl.value.replace(key, newValue);
19
+ }
20
+ });
21
+ },
22
+ };
23
+ const plugins = [transformPlugin];
24
+ const processor = postcss(plugins);
25
+ const transform = async () => {
26
+ const files = await glob(globPath, { ignore: ['node_modules/**'] });
27
+ const filePromises = files.map(async (file) => {
28
+ const contents = fs.readFileSync(file).toString();
29
+ const result = await processor.process(contents, { from: undefined });
30
+ fs.writeFileSync(file, result.css);
31
+ });
32
+ await Promise.all(filePromises);
33
+ };
34
+ // Run the transform.
35
+ void transform();
36
+ };
@@ -0,0 +1,8 @@
1
+ import lightDark from './light-dark.js';
2
+ import tokensv2 from './tokens-v2.js';
3
+ import prefixDs from './prefix-ds.js';
4
+ export default {
5
+ 'tokens-rename-light-dark': lightDark,
6
+ 'tokens-v2': tokensv2,
7
+ 'css-prefix-ds': prefixDs,
8
+ };
@@ -0,0 +1,22 @@
1
+ import { cssVarCodemod } from '../codemods/css-var-codemod.js';
2
+ export default (glob) => cssVarCodemod({
3
+ globPath: glob,
4
+ dictionary: {
5
+ '--fds-semantic-surface-first-light': '--fds-semantic-surface-first-subtle',
6
+ '--fds-semantic-surface-first-light-hover': '--fds-semantic-surface-first-subtle-hover',
7
+ '--fds-semantic-surface-first-light-active': '--fds-semantic-surface-first-subtle-active',
8
+ '--fds-semantic-surface-first-dark': '--fds-semantic-surface-first-strong',
9
+ '--fds-semantic-surface-second-light': '--fds-semantic-surface-second-subtle',
10
+ '--fds-semantic-surface-second-light-hover': '--fds-semantic-surface-second-subtle-hover',
11
+ '--fds-semantic-surface-second-light-active': '--fds-semantic-surface-second-subtle-active',
12
+ '--fds-semantic-surface-second-dark': '--fds-semantic-surface-second-strong',
13
+ '--fds-semantic-surface-third-light': '--fds-semantic-surface-third-subtle',
14
+ '--fds-semantic-surface-third-light-hover': '--fds-semantic-surface-third-subtle-hover',
15
+ '--fds-semantic-surface-third-light-active': '--fds-semantic-surface-third-subtle-active',
16
+ '--fds-semantic-surface-third-dark': '--fds-semantic-surface-third-strong',
17
+ '--fds-semantic-surface-neutral-dark': '--fds-semantic-surface-neutral-strong',
18
+ '--fds-semantic-surface-neutral-dark-hover': '--fds-semantic-surface-neutral-strong-hover',
19
+ '--fds-semantic-border-action-dark': '--fds-semantic-border-action-strong',
20
+ '--fds-semantic-border-action-dark-hover': '--fds-semantic-border-action-strong-hover',
21
+ },
22
+ });
@@ -0,0 +1,7 @@
1
+ import { cssVarCodemod } from '../codemods/css-var-codemod.js';
2
+ export default (glob) => cssVarCodemod({
3
+ globPath: glob,
4
+ dictionary: {
5
+ '--fds': '--ds',
6
+ },
7
+ });
@@ -0,0 +1,210 @@
1
+ import { cssVarCodemod } from '../codemods/css-var-codemod.js';
2
+ export default (glob) => cssVarCodemod({
3
+ globPath: glob,
4
+ dictionary: {
5
+ '--fds-semantic-surface-first-light': '--fds-color-brand1-surface-default',
6
+ '--fds-semantic-surface-first-light-hover': '--fds-color-brand1-surface-hover',
7
+ '--fds-semantic-surface-first-light-active': '--fds-color-brand1-surface-active',
8
+ '--fds-semantic-surface-first-dark': '',
9
+ '--fds-semantic-surface-second-light': '--fds-color-brand2-surface-default',
10
+ '--fds-semantic-surface-second-light-hover': '--fds-color-brand2-surface-hover',
11
+ '--fds-semantic-surface-second-light-active': '--fds-color-brand2-surface-active',
12
+ '--fds-semantic-surface-second-dark': '',
13
+ '--fds-semantic-surface-third-light': '--fds-color-brand3-surface-default',
14
+ '--fds-semantic-surface-third-light-hover': '--fds-color-brand3-surface-hover',
15
+ '--fds-semantic-surface-third-light-active': '--fds-color-brand3-surface-active',
16
+ '--fds-semantic-surface-third-dark': '',
17
+ '--fds-semantic-surface-action-first-subtle': '--fds-color-accent-surface-default',
18
+ '--fds-semantic-surface-action-first-subtle-hover': '--fds-color-accent-surface-hover',
19
+ '--fds-semantic-surface-action-first-default': '--fds-color-accent-base-default',
20
+ '--fds-semantic-surface-action-first-hover': '--fds-color-accent-base-hover',
21
+ '--fds-semantic-surface-action-first-active': '--fds-color-accent-base-active',
22
+ '--fds-semantic-surface-action-first-no_fill': '--fds-color-accent-contrast-first',
23
+ '--fds-semantic-surface-action-first-no_fill-hover': '--fds-color-accent-surface-default',
24
+ '--fds-semantic-surface-action-first-no_fill-active': '--fds-color-accent-surface-hover',
25
+ '--fds-semantic-surface-action-second-subtle': '--fds-color-accent-surface-default',
26
+ '--fds-semantic-surface-action-second-subtle-hover': '--fds-color-accent-surface-hover',
27
+ '--fds-semantic-surface-action-second-default': '--fds-color-accent-base-default',
28
+ '--fds-semantic-surface-action-second-hover': '--fds-color-accent-base-hover',
29
+ '--fds-semantic-surface-action-second-active': '--fds-color-accent-base-active',
30
+ '--fds-semantic-surface-action-second-no_fill': '--fds-color-accent-contrast-first',
31
+ '--fds-semantic-surface-action-second-no_fill-hover': '--fds-color-accent-surface-default',
32
+ '--fds-semantic-surface-action-second-no_fill-active': '--fds-color-accent-surface-hover',
33
+ '--fds-semantic-surface-action-subtle': '--fds-color-accent-surface-default',
34
+ '--fds-semantic-surface-action-subtle-hover': '--fds-color-accent-surface-hover',
35
+ '--fds-semantic-surface-action-default': '--fds-color-accent-base-default',
36
+ '--fds-semantic-surface-action-hover': '--fds-color-accent-base-hover',
37
+ '--fds-semantic-surface-action-active': '--fds-color-accent-base-active',
38
+ '--fds-semantic-surface-action-no_fill': '--fds-color-accent-contrast-first',
39
+ '--fds-semantic-surface-action-no_fill-hover': '--fds-color-accent-surface-default',
40
+ '--fds-semantic-surface-action-no_fill-active': '--fds-color-accent-surface-hover',
41
+ '--fds-semantic-surface-action-checked': '--fds-color-accent-base-default',
42
+ '--fds-semantic-surface-neutral-default': '--fds-color-neutral-background-default',
43
+ '--fds-semantic-surface-neutral-selected': '',
44
+ '--fds-semantic-surface-neutral-subtle': '--fds-color-neutral-background-subtle',
45
+ '--fds-semantic-surface-neutral-subtle-hover': '--fds-color-neutral-surface-default',
46
+ '--fds-semantic-surface-neutral-dark': '--fds-color-neutral-base-default',
47
+ '--fds-semantic-surface-neutral-dark-hover': '--fds-color-neutral-base-hover',
48
+ '--fds-semantic-surface-neutral-inverted': '',
49
+ '--fds-semantic-surface-success-subtle': '--fds-color-success-surface-default',
50
+ '--fds-semantic-surface-success-subtle-hover': '--fds-color-success-surface-hover',
51
+ '--fds-semantic-surface-success-default': '--fds-color-success-base-default',
52
+ '--fds-semantic-surface-success-hover': '--fds-color-success-base-hover',
53
+ '--fds-semantic-surface-success-active': '--fds-color-success-base-active',
54
+ '--fds-semantic-surface-success-no_fill': '--fds-color-success-contrast-first',
55
+ '--fds-semantic-surface-success-no_fill-hover': '--fds-color-success-surface-default',
56
+ '--fds-semantic-surface-success-no_fill-active': '--fds-color-success-surface-hover',
57
+ '--fds-semantic-surface-warning-subtle': '--fds-color-warning-surface-default',
58
+ '--fds-semantic-surface-warning-subtle-hover': '--fds-color-warning-surface-hover',
59
+ '--fds-semantic-surface-warning-default': '--fds-color-warning-base-default',
60
+ '--fds-semantic-surface-warning-default-hover': '--fds-color-warning-base-hover',
61
+ '--fds-semantic-surface-danger-subtle': '--fds-color-danger-surface-default',
62
+ '--fds-semantic-surface-danger-subtle-hover': '--fds-color-danger-surface-hover',
63
+ '--fds-semantic-surface-danger-default': '--fds-color-danger-base-default',
64
+ '--fds-semantic-surface-danger-hover': '--fds-color-danger-base-hover',
65
+ '--fds-semantic-surface-danger-active': '--fds-color-danger-base-active',
66
+ '--fds-semantic-surface-danger-no_fill': '--fds-color-danger-contrast-first',
67
+ '--fds-semantic-surface-danger-no_fill-hover': '--fds-color-danger-surface-default',
68
+ '--fds-semantic-surface-danger-no_fill-active': '--fds-color-danger-surface-hover',
69
+ '--fds-semantic-surface-info-subtle': '',
70
+ '--fds-semantic-surface-info-subtle-hover': '',
71
+ '--fds-semantic-surface-on_inverted-default': '',
72
+ '--fds-semantic-surface-on_inverted-hover': '',
73
+ '--fds-semantic-surface-on_inverted-active': '',
74
+ '--fds-semantic-surface-on_inverted-no_fill': '',
75
+ '--fds-semantic-surface-on_inverted-no_fill-hover': '',
76
+ '--fds-semantic-surface-on_inverted-no_fill-active': '',
77
+ '--fds-semantic-surface-focus-default': '',
78
+ '--fds-semantic-border-first-default': '',
79
+ '--fds-semantic-border-first-hover': '',
80
+ '--fds-semantic-border-first-active': '',
81
+ '--fds-semantic-border-second-default': '',
82
+ '--fds-semantic-border-second-hover': '',
83
+ '--fds-semantic-border-second-active': '',
84
+ '--fds-semantic-border-third-default': '',
85
+ '--fds-semantic-border-third-hover': '',
86
+ '--fds-semantic-border-third-active': '',
87
+ '--fds-semantic-border-action-first-subtle': '',
88
+ '--fds-semantic-border-action-first-subtle-hover': '',
89
+ '--fds-semantic-border-action-first-default': '',
90
+ '--fds-semantic-border-action-first-hover': '',
91
+ '--fds-semantic-border-action-first-active': '',
92
+ '--fds-semantic-border-action-second-subtle': '',
93
+ '--fds-semantic-border-action-second-subtle-hover': '',
94
+ '--fds-semantic-border-action-second-default': '',
95
+ '--fds-semantic-border-action-second-hover': '',
96
+ '--fds-semantic-border-action-second-active': '',
97
+ '--fds-semantic-border-action-subtle': '',
98
+ '--fds-semantic-border-action-subtle-hover': '',
99
+ '--fds-semantic-border-action-default': '',
100
+ '--fds-semantic-border-action-hover': '',
101
+ '--fds-semantic-border-action-active': '',
102
+ '--fds-semantic-border-action-dark': '',
103
+ '--fds-semantic-border-action-dark-hover': '',
104
+ '--fds-semantic-border-info-default': '',
105
+ '--fds-semantic-border-neutral-default': '',
106
+ '--fds-semantic-border-neutral-subtle': '',
107
+ '--fds-semantic-border-neutral-strong': '',
108
+ '--fds-semantic-border-success-default': '',
109
+ '--fds-semantic-border-success-hover': '',
110
+ '--fds-semantic-border-success-active': '',
111
+ '--fds-semantic-border-warning-default': '',
112
+ '--fds-semantic-border-warning-hover': '',
113
+ '--fds-semantic-border-warning-active': '',
114
+ '--fds-semantic-border-danger-default': '',
115
+ '--fds-semantic-border-danger-hover': '',
116
+ '--fds-semantic-border-danger-active': '',
117
+ '--fds-semantic-border-focus-outline': '',
118
+ '--fds-semantic-border-focus-boxshadow': '',
119
+ '--fds-semantic-border-on_inverted-default': '',
120
+ '--fds-semantic-border-input-default': '',
121
+ '--fds-semantic-border-input-hover': '',
122
+ '--fds-semantic-border-divider-default': '',
123
+ '--fds-semantic-border-divider-subtle': '',
124
+ '--fds-semantic-border-divider-strong': '',
125
+ '--fds-semantic-text-action-first-default': '',
126
+ '--fds-semantic-text-action-first-hover': '',
127
+ '--fds-semantic-text-action-first-active': '',
128
+ '--fds-semantic-text-action-first-on_action': '',
129
+ '--fds-semantic-text-action-second-default': '',
130
+ '--fds-semantic-text-action-second-hover': '',
131
+ '--fds-semantic-text-action-second-active': '',
132
+ '--fds-semantic-text-action-second-on_action': '',
133
+ '--fds-semantic-text-action-default': '',
134
+ '--fds-semantic-text-action-hover': '',
135
+ '--fds-semantic-text-action-active': '',
136
+ '--fds-semantic-text-action-on_action': '',
137
+ '--fds-semantic-text-success-default': '',
138
+ '--fds-semantic-text-success-hover': '',
139
+ '--fds-semantic-text-success-active': '',
140
+ '--fds-semantic-text-success-on_success': '',
141
+ '--fds-semantic-text-success-on_success_subtle': '',
142
+ '--fds-semantic-text-neutral-default': '',
143
+ '--fds-semantic-text-neutral-subtle': '',
144
+ '--fds-semantic-text-neutral-on_inverted': '',
145
+ '--fds-semantic-text-warning-default': '',
146
+ '--fds-semantic-text-warning-icon_warning': '',
147
+ '--fds-semantic-text-warning-on_warning': '',
148
+ '--fds-semantic-text-danger-default': '',
149
+ '--fds-semantic-text-danger-hover': '',
150
+ '--fds-semantic-text-danger-active': '',
151
+ '--fds-semantic-text-danger-on_danger': '',
152
+ '--fds-semantic-text-danger-on_danger_subtle': '',
153
+ '--fds-semantic-text-visited-default': '',
154
+ '--fds-semantic-background-default': '',
155
+ '--fds-semantic-background-subtle': '',
156
+ '--fds-typography-heading-2xlarge': '',
157
+ '--fds-typography-heading-xlarge': '',
158
+ '--fds-typography-heading-large': '',
159
+ '--fds-typography-heading-medium': '',
160
+ '--fds-typography-heading-small': '',
161
+ '--fds-typography-heading-xsmall': '',
162
+ '--fds-typography-heading-xxsmall': '',
163
+ '--fds-typography-ingress-large': '',
164
+ '--fds-typography-ingress-medium': '',
165
+ '--fds-typography-ingress-small': '',
166
+ '--fds-typography-ingress-xsmall': '',
167
+ '--fds-typography-paragraph-large': '',
168
+ '--fds-typography-paragraph-medium': '',
169
+ '--fds-typography-paragraph-small': '',
170
+ '--fds-typography-paragraph-xsmall': '',
171
+ '--fds-typography-paragraph-short-large': '',
172
+ '--fds-typography-paragraph-short-medium': '',
173
+ '--fds-typography-paragraph-short-small': '',
174
+ '--fds-typography-paragraph-short-xsmall': '',
175
+ '--fds-typography-paragraph-long-large': '',
176
+ '--fds-typography-paragraph-long-medium': '',
177
+ '--fds-typography-paragraph-long-small': '',
178
+ '--fds-typography-paragraph-long-xsmall': '',
179
+ '--fds-typography-label-large': '',
180
+ '--fds-typography-label-medium': '',
181
+ '--fds-typography-label-small': '',
182
+ '--fds-typography-label-xsmall': '',
183
+ '--fds-typography-error_message-large': '',
184
+ '--fds-typography-error_message-medium': '',
185
+ '--fds-typography-error_message-small': '',
186
+ '--fds-typography-error_message-xsmall': '',
187
+ '--fds-typography-interactive-large': '--fds-typography-paragraph-short-large',
188
+ '--fds-typography-interactive-medium': '--fds-typography-paragraph-short-medium',
189
+ '--fds-typography-interactive-small': '--fds-typography-paragraph-short-small',
190
+ '--fds-border_radius-interactive': '--fds-border-radius-md',
191
+ '--fds-border_radius-small': '--fds-border-radius-sm',
192
+ '--fds-border_radius-medium': '--fds-border-radius-md',
193
+ '--fds-border_radius-large': '--fds-border-radius-lg',
194
+ '--fds-border_radius-xlarge': '--fds-border-radius-xl',
195
+ '--fds-border_radius-xxlarge': '--fds-border-radius-2xl',
196
+ '--fds-border_radius-xxxlarge': '--fds-border-radius-3xl',
197
+ '--fds-border_radius-xxxxlarge': '--fds-border-radius-4xl',
198
+ '--fds-border_radius-full': '--fds-border-radius-full',
199
+ '--fds-base_spacing': '[delete]',
200
+ '--fds-base_sizing': '[delete]',
201
+ '--fds-border_width-default': '--fds-border-width-default',
202
+ '--fds-border_width-active': '--fds-border-width-active',
203
+ '--fds-border_width-tab_focus': '--fds-border-width-tab_focus', // Skulle denne fjernes?
204
+ '--fds-shadow-xsmall': '--fds-shadow-xs',
205
+ '--fds-shadow-small': '--fds-shadow-sm',
206
+ '--fds-shadow-medium': '--fds-shadow-md',
207
+ '--fds-shadow-large': '--fds-shadow-lg',
208
+ '--fds-shadow-xlarge': '--fds-shadow-xl',
209
+ },
210
+ });
@@ -0,0 +1,140 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import { registerTransforms, permutateThemes } from '@tokens-studio/sd-transforms';
4
+ import StyleDictionary from 'style-dictionary';
5
+ import * as R from 'ramda';
6
+ import { nameKebab, typographyShorthand, sizeRem } from './transformers.js';
7
+ import { groupedTokens, scopedReferenceVariables } from './formatters.js';
8
+ void registerTransforms(StyleDictionary);
9
+ const prefix = 'fds';
10
+ const basePxFontSize = 16;
11
+ const separator = '_';
12
+ const fileHeader = () => [`These files are generated from design tokens defind using Token Studio`];
13
+ StyleDictionary.registerTransform(sizeRem);
14
+ StyleDictionary.registerTransform(nameKebab);
15
+ StyleDictionary.registerTransform(typographyShorthand);
16
+ StyleDictionary.registerFormat(groupedTokens);
17
+ StyleDictionary.registerFormat(scopedReferenceVariables);
18
+ StyleDictionary.registerTransformGroup({
19
+ name: 'fds/css',
20
+ transforms: [
21
+ `ts/resolveMath`,
22
+ nameKebab.name,
23
+ sizeRem.name,
24
+ typographyShorthand.name,
25
+ 'ts/color/modifiers',
26
+ 'ts/color/css/hexrgba',
27
+ 'ts/size/lineheight',
28
+ 'ts/size/px',
29
+ 'ts/shadow/css/shorthand',
30
+ ],
31
+ });
32
+ const processThemeName = R.pipe(R.replace(`${separator}semantic`, ''), R.toLower, R.split(separator));
33
+ const getCSSConfig = ({ fileName = 'unknown', buildPath = 'unknown' }) => {
34
+ return {
35
+ log: { verbosity: 'verbose' },
36
+ preprocessors: ['tokens-studio'],
37
+ platforms: {
38
+ css: {
39
+ prefix,
40
+ basePxFontSize,
41
+ transformGroup: 'fds/css',
42
+ buildPath,
43
+ files: [
44
+ {
45
+ destination: `${fileName}.css`,
46
+ format: scopedReferenceVariables.name,
47
+ },
48
+ ],
49
+ options: {
50
+ fileHeader,
51
+ includeReferences: (token) => {
52
+ if (R.test(/accent|neutral|brand1|brand2|brand3|success|danger|warning/, token.name) &&
53
+ R.includes('semantic/color', token.filePath)) {
54
+ return true;
55
+ }
56
+ return false;
57
+ },
58
+ },
59
+ },
60
+ },
61
+ };
62
+ };
63
+ const getStorefrontConfig = ({ fileName = 'unknown', buildPath = 'unknown' }) => {
64
+ return {
65
+ log: { verbosity: 'verbose' },
66
+ preprocessors: ['tokens-studio'],
67
+ platforms: {
68
+ storefront: {
69
+ prefix,
70
+ basePxFontSize,
71
+ transformGroup: 'fds/css',
72
+ buildPath,
73
+ files: [
74
+ {
75
+ destination: `${fileName}.ts`,
76
+ format: groupedTokens.name,
77
+ filter: (token) => {
78
+ return R.not(R.includes('themes', token.filePath));
79
+ },
80
+ },
81
+ ],
82
+ options: {
83
+ fileHeader,
84
+ },
85
+ },
86
+ },
87
+ };
88
+ };
89
+ const sd = new StyleDictionary();
90
+ export async function run(options) {
91
+ const tokensPath = options.tokens;
92
+ const storefrontTokensOutPath = path.resolve('../../apps/storefront/tokens');
93
+ const packageTokensOutPath = path.resolve('../../packages/theme/brand');
94
+ const $themes = JSON.parse(fs.readFileSync(path.resolve(`${tokensPath}/$themes.json`), 'utf-8'));
95
+ const themes = permutateThemes($themes, {
96
+ separator,
97
+ });
98
+ const getConfigs = (configCallback, outPath) => Object.entries(themes)
99
+ .map(([name, tokensets]) => {
100
+ const updatedSets = tokensets.map((x) => `${tokensPath}/${x}.json`);
101
+ const [fileName, folderName] = processThemeName(name);
102
+ const paritionPrimitives = /(?!.*global\.json).*primitives.*/;
103
+ // const paritionPrimitives = /.*primitives.*/;
104
+ const [source, include] = R.partition(R.test(paritionPrimitives), updatedSets);
105
+ const config_ = configCallback({
106
+ fileName: fileName,
107
+ buildPath: `${outPath}/${folderName}/`,
108
+ });
109
+ const config = {
110
+ ...config_,
111
+ source: source,
112
+ include,
113
+ };
114
+ console.log(config);
115
+ return [`${folderName}: ${fileName}`, config];
116
+ })
117
+ .sort();
118
+ const tokenConfigs = getConfigs(getCSSConfig, packageTokensOutPath);
119
+ const storefrontConfigs = getConfigs(getStorefrontConfig, storefrontTokensOutPath);
120
+ if (tokenConfigs.length > 0) {
121
+ console.log('🍱 Staring token builder');
122
+ console.log('➡️ Tokens path: ', tokensPath);
123
+ console.log('\n🏗️ Start building CSS tokens');
124
+ await Promise.all(tokenConfigs.map(async ([name, config]) => {
125
+ console.log(`👷 Processing ${name}`);
126
+ const tokensPackageSD = await sd.extend(config);
127
+ return tokensPackageSD.buildAllPlatforms();
128
+ }));
129
+ console.log('🏁 Finished building package tokens!');
130
+ }
131
+ if (storefrontConfigs.length > 0) {
132
+ console.log('\n🏗️ Started building storefront tokens…');
133
+ await Promise.all(storefrontConfigs.map(async ([name, config]) => {
134
+ console.log(`👷 Processing ${name}`);
135
+ const storefrontSD = await sd.extend(config);
136
+ return storefrontSD.buildAllPlatforms();
137
+ }));
138
+ console.log('🏁 Finished building storefront tokens!');
139
+ }
140
+ }
@@ -0,0 +1,78 @@
1
+ import * as R from 'ramda';
2
+ import { fileHeader, createPropertyFormatter, usesReferences, getReferences } from 'style-dictionary/utils';
3
+ /**
4
+ * CSS variables format with option to include source references for matched token through `options.referencesFilter`
5
+ */
6
+ export const scopedReferenceVariables = {
7
+ name: 'css/variables-scoped-references',
8
+ format: async function ({ dictionary, file, options }) {
9
+ const { allTokens, unfilteredTokens } = dictionary;
10
+ const { usesDtcg, outputReferences } = options;
11
+ const includeReferences = options.includeReferences;
12
+ let referencedTokens = [];
13
+ const format = createPropertyFormatter({
14
+ outputReferences,
15
+ dictionary,
16
+ format: 'css',
17
+ });
18
+ const formatWithReference = createPropertyFormatter({
19
+ outputReferences: true,
20
+ dictionary,
21
+ format: 'css',
22
+ });
23
+ const parseToken = (token, ignoreSource) => {
24
+ const originalValue = (usesDtcg ? token.original.$value : token.original.value);
25
+ if (usesReferences(originalValue) && includeReferences(token)) {
26
+ const refs = getReferences(originalValue, unfilteredTokens ? unfilteredTokens : {});
27
+ referencedTokens = [...referencedTokens, ...refs.filter((x) => x.isSource)];
28
+ return formatWithReference(token);
29
+ }
30
+ if (ignoreSource && !token.isSource) {
31
+ return format(token);
32
+ }
33
+ };
34
+ const tokens = allTokens.map((t) => parseToken(t, true)).filter((x) => x);
35
+ const referenceTokens = referencedTokens
36
+ .reduce((acc, token) => {
37
+ if (acc.find((x) => x.name === token.name)) {
38
+ return acc;
39
+ }
40
+ return [...acc, token];
41
+ }, [])
42
+ .map((token) => format(token))
43
+ .filter((formattedValue) => formattedValue);
44
+ return fileHeader({ file }).then((fileHeaderText) => `
45
+ ${fileHeaderText}
46
+ :root {
47
+ ${referenceTokens.length > 0 ? referenceTokens.join('\n') : ''}
48
+ ${tokens.join('\n')}
49
+ }
50
+ `);
51
+ },
52
+ };
53
+ const groupByType = R.groupBy((token) => token.type);
54
+ /** Add token name with prefix to list for removal */
55
+ const removeUnwatedTokens = R.filter((token) => !['fds-base_spacing', 'fds-base_sizing'].includes(token.name));
56
+ const toCssVarName = R.pipe(R.split(':'), R.head, R.trim);
57
+ /**
58
+ * Format for displaying tokens in storefront
59
+ */
60
+ export const groupedTokens = {
61
+ name: 'groupedTokens',
62
+ format: async function ({ dictionary, file }) {
63
+ const format = createPropertyFormatter({
64
+ dictionary,
65
+ format: 'css',
66
+ });
67
+ const formatTokens = R.map((token) => ({
68
+ ...token,
69
+ name: toCssVarName(format(token)),
70
+ }));
71
+ const processTokens = R.pipe(removeUnwatedTokens, formatTokens, groupByType);
72
+ const tokens = processTokens(dictionary.allTokens);
73
+ const content = Object.entries(tokens)
74
+ .map(([name, token]) => `export const ${name} = ${JSON.stringify(token, null, 2).replace(/"([^"]+)":/g, '$1:')} \n`)
75
+ .join('\n');
76
+ return fileHeader({ file }).then((fileHeaderText) => fileHeaderText + content);
77
+ },
78
+ };
@@ -0,0 +1,30 @@
1
+ // Copied from https://github.com/blakeembrey/change-case/blob/change-case%404.1.2/packages/no-case/src/index.ts
2
+ const lowerCase = (text = '') => text.toLowerCase();
3
+ // Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case").
4
+ const DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
5
+ // Remove all non-word characters.
6
+ const DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
7
+ /**
8
+ * Normalize the string into something other libraries can manipulate easier.
9
+ */
10
+ export function noCase(input, options = {}) {
11
+ const { splitRegexp = DEFAULT_SPLIT_REGEXP, stripRegexp = DEFAULT_STRIP_REGEXP, transform = lowerCase, delimiter = ' ', } = options;
12
+ const result = replace(replace(input, splitRegexp, '$1\0$2'), stripRegexp, '\0');
13
+ let start = 0;
14
+ let end = result.length;
15
+ // Trim the delimiter from around the output string.
16
+ while (result.charAt(start) === '\0')
17
+ start++;
18
+ while (result.charAt(end - 1) === '\0')
19
+ end--;
20
+ // Transform each token independently.
21
+ return result.slice(start, end).split('\0').map(transform).join(delimiter);
22
+ }
23
+ /**
24
+ * Replace `re` in the input string with the replacement value.
25
+ */
26
+ function replace(input, re, value) {
27
+ if (re instanceof RegExp)
28
+ return input.replace(re, value);
29
+ return re.reduce((input, re) => input.replace(re, value), input);
30
+ }
@@ -0,0 +1,39 @@
1
+ import { noCase } from './noCase.js';
2
+ export const sizeRem = {
3
+ name: 'fds/size/toRem',
4
+ type: 'value',
5
+ transitive: true,
6
+ filter: (token) => ['sizing', 'spacing'].includes(token.type) &&
7
+ !token.name.includes('base'),
8
+ transform: (token, config) => {
9
+ const baseFont = config.basePxFontSize || 16;
10
+ const value = parseInt(token.value);
11
+ if (value === 0) {
12
+ return '0';
13
+ }
14
+ return `${value / baseFont}rem`;
15
+ },
16
+ };
17
+ export const nameKebab = {
18
+ name: 'name/cti/hierarchical-kebab',
19
+ type: 'name',
20
+ transform: (token, options) => {
21
+ return noCase([options?.prefix].concat(token.path).join('-'), {
22
+ delimiter: '-',
23
+ stripRegexp: /[^A-Z0-9_]+/gi,
24
+ });
25
+ },
26
+ };
27
+ export const typographyShorthand = {
28
+ name: 'typography/shorthand',
29
+ type: 'value',
30
+ transitive: true,
31
+ filter: (token) => token.type === 'typography',
32
+ transform: (token, config, options) => {
33
+ const { usesDtcg } = options;
34
+ const typography = (usesDtcg ? token.$value : token.value);
35
+ const baseFontPx = config.basePxFontSize || 16;
36
+ const fontSize = `${parseInt(typography.fontSize) / baseFontPx}rem`;
37
+ return `${typography.fontWeight} ${fontSize}/${typography.lineHeight} '${typography.fontFamily}'`;
38
+ },
39
+ };