@digdir/designsystemet 0.1.0-next.21 → 0.1.0-next.22

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 (71) hide show
  1. package/dist/bin/designsystemet.js +2 -2
  2. package/dist/src/migrations/codemods/css/plugins.js +14 -15
  3. package/dist/src/migrations/codemods/jsx/classname-prefix.js +8 -7
  4. package/dist/src/tokens/actions.js +1 -1
  5. package/dist/src/tokens/build.js +26 -15
  6. package/dist/src/tokens/configs.js +20 -16
  7. package/dist/src/tokens/formats/css.js +36 -23
  8. package/dist/src/tokens/formats/js-tokens.js +8 -4
  9. package/dist/src/tokens/transformers.js +7 -3
  10. package/dist/src/tokens/utils/entryfile.js +31 -0
  11. package/dist/src/tokens/utils/permutateThemes.js +2 -2
  12. package/dist/src/tokens/utils/utils.js +11 -0
  13. package/dist/types/bin/designsystemet.d.ts +3 -0
  14. package/dist/types/bin/designsystemet.d.ts.map +1 -0
  15. package/dist/types/src/colors/colorUtils.d.ts +126 -0
  16. package/dist/types/src/colors/colorUtils.d.ts.map +1 -0
  17. package/dist/types/src/colors/index.d.ts +4 -0
  18. package/dist/types/src/colors/index.d.ts.map +1 -0
  19. package/dist/types/src/colors/themeUtils.d.ts +102 -0
  20. package/dist/types/src/colors/themeUtils.d.ts.map +1 -0
  21. package/dist/types/src/colors/types.d.ts +16 -0
  22. package/dist/types/src/colors/types.d.ts.map +1 -0
  23. package/dist/types/src/init/createTokensPackage.d.ts +5 -0
  24. package/dist/types/src/init/createTokensPackage.d.ts.map +1 -0
  25. package/dist/types/src/init/generateMetadataJson.d.ts +6 -0
  26. package/dist/types/src/init/generateMetadataJson.d.ts.map +1 -0
  27. package/dist/types/src/init/generateThemesJson.d.ts +3 -0
  28. package/dist/types/src/init/generateThemesJson.d.ts.map +1 -0
  29. package/dist/types/src/init/index.d.ts +3 -0
  30. package/dist/types/src/init/index.d.ts.map +1 -0
  31. package/dist/types/src/init/nextStepsMarkdown.d.ts +3 -0
  32. package/dist/types/src/init/nextStepsMarkdown.d.ts.map +1 -0
  33. package/dist/types/src/init/template/prettier.config.d.mts +9 -0
  34. package/dist/types/src/init/template/prettier.config.d.mts.map +1 -0
  35. package/dist/types/src/init/utils.d.ts +4 -0
  36. package/dist/types/src/init/utils.d.ts.map +1 -0
  37. package/dist/types/src/migrations/beta-to-v1.d.ts +3 -0
  38. package/dist/types/src/migrations/beta-to-v1.d.ts.map +1 -0
  39. package/dist/types/src/migrations/codemods/css/plugins.d.ts +6 -0
  40. package/dist/types/src/migrations/codemods/css/plugins.d.ts.map +1 -0
  41. package/dist/types/src/migrations/codemods/css/run.d.ts +8 -0
  42. package/dist/types/src/migrations/codemods/css/run.d.ts.map +1 -0
  43. package/dist/types/src/migrations/codemods/jsx/classname-prefix.d.ts +10 -0
  44. package/dist/types/src/migrations/codemods/jsx/classname-prefix.d.ts.map +1 -0
  45. package/dist/types/src/migrations/codemods/jsx/run.d.ts +7 -0
  46. package/dist/types/src/migrations/codemods/jsx/run.d.ts.map +1 -0
  47. package/dist/types/src/migrations/index.d.ts +6 -0
  48. package/dist/types/src/migrations/index.d.ts.map +1 -0
  49. package/dist/types/src/migrations/react-beta-to-v1.d.ts +3 -0
  50. package/dist/types/src/migrations/react-beta-to-v1.d.ts.map +1 -0
  51. package/dist/types/src/tokens/actions.d.ts +6 -0
  52. package/dist/types/src/tokens/actions.d.ts.map +1 -0
  53. package/dist/types/src/tokens/build.d.ts +11 -0
  54. package/dist/types/src/tokens/build.d.ts.map +1 -0
  55. package/dist/types/src/tokens/configs.d.ts +31 -0
  56. package/dist/types/src/tokens/configs.d.ts.map +1 -0
  57. package/dist/types/src/tokens/formats/css.d.ts +5 -0
  58. package/dist/types/src/tokens/formats/css.d.ts.map +1 -0
  59. package/dist/types/src/tokens/formats/js-tokens.d.ts +6 -0
  60. package/dist/types/src/tokens/formats/js-tokens.d.ts.map +1 -0
  61. package/dist/types/src/tokens/transformers.d.ts +5 -0
  62. package/dist/types/src/tokens/transformers.d.ts.map +1 -0
  63. package/dist/types/src/tokens/utils/entryfile.d.ts +11 -0
  64. package/dist/types/src/tokens/utils/entryfile.d.ts.map +1 -0
  65. package/dist/types/src/tokens/utils/noCase.d.ts +11 -0
  66. package/dist/types/src/tokens/utils/noCase.d.ts.map +1 -0
  67. package/dist/types/src/tokens/utils/permutateThemes.d.ts +17 -0
  68. package/dist/types/src/tokens/utils/permutateThemes.d.ts.map +1 -0
  69. package/dist/types/src/tokens/utils/utils.d.ts +25 -0
  70. package/dist/types/src/tokens/utils/utils.d.ts.map +1 -0
  71. package/package.json +24 -22
@@ -15,9 +15,9 @@ program.command("tokens").showHelpAfterError().description("run Designsystemet t
15
15
  program.command("migrate").showHelpAfterError().description("run a Designsystemet migration").addArgument(new Argument("[migration]", "Available migrations").choices(Object.keys(migrations))).option("-l --list", "List available migrations").option("-g --glob <glob>", "Glob for files upon which to apply the migration", "./**/*.(tsx|css)").action((migrationKey, opts) => {
16
16
  const { glob, list } = opts;
17
17
  if (list) {
18
- Object.keys(migrations).forEach((key) => {
18
+ for (const key of Object.keys(migrations)) {
19
19
  console.log(key);
20
- });
20
+ }
21
21
  } else if (migrationKey) {
22
22
  const migration = migrations[migrationKey];
23
23
  if (!migration) {
@@ -8,11 +8,11 @@ const cssClassRename = (dictionary) => ({
8
8
  Rule(rule) {
9
9
  const selector = rule.selector;
10
10
  if (!selector) return;
11
- Object.entries(dictionary).forEach(([from, to]) => {
11
+ for (const [from, to] of Object.entries(dictionary)) {
12
12
  if (!selector.includes(from)) return;
13
13
  const newSelector = selector.replace(new RegExp(from, "g"), to);
14
14
  rule.selector = newSelector;
15
- });
15
+ }
16
16
  }
17
17
  });
18
18
  const cssVarRename = (dictionary) => ({
@@ -20,22 +20,21 @@ const cssVarRename = (dictionary) => ({
20
20
  Declaration(decl) {
21
21
  const { value, prop } = decl;
22
22
  const deleted = /* @__PURE__ */ new Set();
23
- Object.entries(dictionary).forEach(([from, to]) => {
23
+ for (const [from, to] of Object.entries(dictionary)) {
24
24
  if (!R.isEmpty(to)) {
25
- switch (true) {
26
- case R.includes(from, value):
27
- to === "[delete]" && deleted.add(deleteMsg(decl, from));
28
- decl.value = value.replace(from, to);
29
- break;
30
- case R.includes(from, prop):
31
- if (decl.variable) {
32
- to === "[delete]" && deleted.add(deleteMsg(decl, from));
33
- decl.prop = prop.replace(from, to);
34
- break;
35
- }
25
+ if (R.includes(from, value)) {
26
+ if (to === "[delete]") {
27
+ deleted.add(deleteMsg(decl, from));
28
+ }
29
+ decl.value = value.replace(from, to);
30
+ } else if (R.includes(from, prop) && decl.variable) {
31
+ if (to === "[delete]") {
32
+ deleted.add(deleteMsg(decl, from));
33
+ }
34
+ decl.prop = prop.replace(from, to);
36
35
  }
37
36
  }
38
- });
37
+ }
39
38
  if (deleted.size > 0) {
40
39
  Array.from(deleted).forEach(printDelete);
41
40
  }
@@ -5,11 +5,11 @@ const replaceInLiteral = (node) => {
5
5
  return node;
6
6
  };
7
7
  const replaceInTemplateLiteral = (node) => {
8
- node.forEach((element) => {
8
+ for (const element of node) {
9
9
  const value = element.value.raw;
10
- if (typeof value !== "string") return;
10
+ if (typeof value !== "string") continue;
11
11
  element.value.raw = replaceInLiteral(value);
12
- });
12
+ }
13
13
  };
14
14
  const processNode = (node) => {
15
15
  if (!node) return;
@@ -46,11 +46,12 @@ const processNode = (node) => {
46
46
  function replaceClassNamePrefix(file, api) {
47
47
  const j = api.jscodeshift;
48
48
  const root = j(file.source);
49
- root.find(j.JSXElement).forEach((path) => {
50
- j(path).find(j.JSXAttribute, { name: { name: "className" } }).forEach((nodePath) => {
49
+ for (const path of root.find(j.JSXElement).paths()) {
50
+ const nodes = j(path).find(j.JSXAttribute, { name: { name: "className" } });
51
+ for (const nodePath of nodes.paths()) {
51
52
  processNode(nodePath.value.value);
52
- });
53
- });
53
+ }
54
+ }
54
55
  return root.toSource({
55
56
  quote: "single",
56
57
  reuseWhitespace: true,
@@ -18,7 +18,7 @@ const makeEntryFile = {
18
18
  }
19
19
  const generateImportUrls = R.pipe(
20
20
  sortLightmodeFirst,
21
- R.map((file) => `@import url('./${theme}/${file.toString()}');`),
21
+ R.map((file) => `@import url('${theme}/${file.toString()}');`),
22
22
  R.join("\n")
23
23
  );
24
24
  const files = await glob(`**/*`, { cwd: platform.buildPath });
@@ -4,12 +4,13 @@ import chalk from "chalk";
4
4
  import * as R from "ramda";
5
5
  import StyleDictionary from "style-dictionary";
6
6
  import * as configs from "./configs.js";
7
+ import { makeEntryFile } from "./utils/entryfile.js";
7
8
  const { permutateThemes, getConfigs } = configs;
8
9
  const sd = new StyleDictionary();
9
10
  async function run(options) {
10
11
  const tokensDir = options.tokens;
11
12
  const storefrontOutDir = path.resolve("../../apps/storefront/tokens");
12
- const tokensOutDir = path.resolve(options.out);
13
+ const outPath = path.resolve(options.out);
13
14
  const $themes = JSON.parse(fs.readFileSync(path.resolve(`${tokensDir}/$themes.json`), "utf-8"));
14
15
  const relevant$themes = $themes.filter((theme) => {
15
16
  const group = R.toLower(R.defaultTo("")(theme.group));
@@ -20,9 +21,9 @@ async function run(options) {
20
21
  const typographyThemes = R.filter((val) => val.mode === "light", themes);
21
22
  const colormodeThemes = R.filter((val) => val.typography === "primary", themes);
22
23
  const semanticThemes = R.filter((val) => val.mode === "light" && val.typography === "primary", themes);
23
- const colorModeConfigs = getConfigs(configs.colorModeVariables, tokensOutDir, tokensDir, colormodeThemes);
24
- const semanticConfigs = getConfigs(configs.semanticVariables, tokensOutDir, tokensDir, semanticThemes);
25
- const typographyConfigs = getConfigs(configs.typographyCSS, tokensOutDir, tokensDir, typographyThemes);
24
+ const colorModeConfigs = getConfigs(configs.colorModeVariables, outPath, tokensDir, colormodeThemes);
25
+ const semanticConfigs = getConfigs(configs.semanticVariables, outPath, tokensDir, semanticThemes);
26
+ const typographyConfigs = getConfigs(configs.typographyCSS, outPath, tokensDir, typographyThemes);
26
27
  const storefrontConfigs = getConfigs(configs.typescriptTokens, storefrontOutDir, tokensDir, colormodeThemes);
27
28
  if (typographyConfigs.length > 0) {
28
29
  console.log(`
@@ -35,17 +36,6 @@ async function run(options) {
35
36
  })
36
37
  );
37
38
  }
38
- if (semanticConfigs.length > 0) {
39
- console.log(`
40
- \u{1F371} Building ${chalk.green("semantic")}`);
41
- await Promise.all(
42
- semanticConfigs.map(async ({ theme, config, semantic }) => {
43
- console.log(`\u{1F477} ${theme} - ${semantic}`);
44
- const typographyClasses = await sd.extend(config);
45
- return typographyClasses.buildAllPlatforms();
46
- })
47
- );
48
- }
49
39
  if (colorModeConfigs.length > 0) {
50
40
  console.log(`
51
41
  \u{1F371} Building ${chalk.green("color-mode")}`);
@@ -57,6 +47,17 @@ async function run(options) {
57
47
  })
58
48
  );
59
49
  }
50
+ if (semanticConfigs.length > 0) {
51
+ console.log(`
52
+ \u{1F371} Building ${chalk.green("semantic")}`);
53
+ await Promise.all(
54
+ semanticConfigs.map(async ({ theme, config, semantic }) => {
55
+ console.log(`\u{1F477} ${theme} - ${semantic}`);
56
+ const typographyClasses = await sd.extend(config);
57
+ return typographyClasses.buildAllPlatforms();
58
+ })
59
+ );
60
+ }
60
61
  if (storefrontConfigs.length > 0 && options.preview) {
61
62
  console.log(`
62
63
  \u{1F371} Building ${chalk.green("Storefront preview tokens")}`);
@@ -68,6 +69,16 @@ async function run(options) {
68
69
  })
69
70
  );
70
71
  }
72
+ if (semanticConfigs.length > 0) {
73
+ console.log(`
74
+ \u{1F371} Building ${chalk.green("CSS file")}`);
75
+ await Promise.all(
76
+ semanticConfigs.map(async ({ theme }) => {
77
+ console.log(`\u{1F477} ${theme}.css`);
78
+ return makeEntryFile({ theme, outPath, buildPath: path.resolve(`${outPath}/${theme}`) });
79
+ })
80
+ );
81
+ }
71
82
  }
72
83
  export {
73
84
  run
@@ -1,14 +1,14 @@
1
- import * as tokenStudio from "@tokens-studio/sd-transforms";
1
+ import { register } from "@tokens-studio/sd-transforms";
2
2
  import * as R from "ramda";
3
3
  import StyleDictionary from "style-dictionary";
4
4
  import { outputReferencesFilter } from "style-dictionary/utils";
5
- import { makeEntryFile } from "./actions.js";
6
5
  import * as formats from "./formats/css.js";
7
6
  import { jsTokens } from "./formats/js-tokens.js";
8
7
  import { nameKebab, sizeRem, typographyShorthand } from "./transformers.js";
9
8
  import { permutateThemes as permutateThemes_ } from "./utils/permutateThemes.js";
10
- import { typeEquals } from "./utils/utils.js";
11
- void tokenStudio.registerTransforms(StyleDictionary);
9
+ import { pathStartsWithOneOf, typeEquals } from "./utils/utils.js";
10
+ void register(StyleDictionary, { withSDBuiltins: false });
11
+ const usesDtcg = true;
12
12
  const prefix = "ds";
13
13
  const basePxFontSize = 16;
14
14
  const separator = "_";
@@ -20,7 +20,6 @@ StyleDictionary.registerFormat(jsTokens);
20
20
  StyleDictionary.registerFormat(formats.colormode);
21
21
  StyleDictionary.registerFormat(formats.semantic);
22
22
  StyleDictionary.registerFormat(formats.typography);
23
- StyleDictionary.registerAction(makeEntryFile);
24
23
  const dsTransformers = [
25
24
  nameKebab.name,
26
25
  `ts/resolveMath`,
@@ -31,7 +30,7 @@ const dsTransformers = [
31
30
  "ts/color/modifiers",
32
31
  "ts/color/css/hexrgba",
33
32
  "ts/size/lineheight",
34
- "ts/shadow/css/shorthand"
33
+ "shadow/css/shorthand"
35
34
  ];
36
35
  const paritionPrimitives = R.partition(R.test(/(?!.*global\.json).*primitives.*/));
37
36
  const hasUnknownProps = R.pipe(R.values, R.none(R.equals("unknown")), R.not);
@@ -48,6 +47,7 @@ const colorModeVariables = ({ mode = "light", outPath, theme }) => {
48
47
  const selector = `${mode === "light" ? ":root, " : ""}[data-ds-color-mode="${mode}"]`;
49
48
  const layer = `ds.theme.color-mode.${mode}`;
50
49
  return {
50
+ usesDtcg,
51
51
  log: { verbosity: "silent" },
52
52
  preprocessors: ["tokens-studio"],
53
53
  platforms: {
@@ -62,7 +62,6 @@ const colorModeVariables = ({ mode = "light", outPath, theme }) => {
62
62
  prefix,
63
63
  buildPath: `${outPath}/${theme}/`,
64
64
  transforms: dsTransformers,
65
- actions: [makeEntryFile.name],
66
65
  files: [
67
66
  {
68
67
  destination: `color-mode/${mode}.css`,
@@ -81,8 +80,9 @@ const colorModeVariables = ({ mode = "light", outPath, theme }) => {
81
80
  const semanticVariables = ({ outPath, theme }) => {
82
81
  const selector = `:root`;
83
82
  const layer = `ds.theme.semantic`;
84
- const isCalculatedToken = (token) => typeEquals(["spacing", "sizing", "borderRadius"], token);
83
+ const isCalculatedToken = (token) => pathStartsWithOneOf(["spacing", "sizing", "border-radius"], token);
85
84
  return {
85
+ usesDtcg,
86
86
  log: { verbosity: "silent" },
87
87
  preprocessors: ["tokens-studio"],
88
88
  platforms: {
@@ -98,12 +98,11 @@ const semanticVariables = ({ outPath, theme }) => {
98
98
  prefix,
99
99
  buildPath: `${outPath}/${theme}/`,
100
100
  transforms: dsTransformers,
101
- actions: [makeEntryFile.name],
102
101
  files: [
103
102
  {
104
103
  destination: `semantic.css`,
105
104
  format: formats.semantic.name,
106
- filter: (token) => (!token.isSource || isCalculatedToken(token)) && !typeEquals(["color", "fontWeights", "fontFamilies"], token)
105
+ filter: (token) => (!token.isSource || isCalculatedToken(token)) && !typeEquals(["color", "fontWeight", "fontFamily"], token)
107
106
  }
108
107
  ],
109
108
  options: {
@@ -116,6 +115,7 @@ const semanticVariables = ({ outPath, theme }) => {
116
115
  };
117
116
  const typescriptTokens = ({ mode = "unknown", outPath, theme }) => {
118
117
  return {
118
+ usesDtcg,
119
119
  log: { verbosity: "silent" },
120
120
  preprocessors: ["tokens-studio"],
121
121
  platforms: {
@@ -130,9 +130,8 @@ const typescriptTokens = ({ mode = "unknown", outPath, theme }) => {
130
130
  format: jsTokens.name,
131
131
  outputReferences: outputColorReferences,
132
132
  filter: (token) => {
133
- if (R.test(/primitives\/modes|\/themes/, token.filePath)) {
134
- return false;
135
- }
133
+ if (R.test(/primitives\/modes|\/themes/, token.filePath)) return false;
134
+ if (pathStartsWithOneOf(["border-width"], token)) return false;
136
135
  if (R.test(/accent|neutral|brand1|brand2|brand3|success|danger|warning/, token.name) || R.includes("semantic", token.filePath)) {
137
136
  return true;
138
137
  }
@@ -151,6 +150,7 @@ const typographyCSS = ({ outPath, theme, typography }) => {
151
150
  const selector = `${typography === "primary" ? ":root, " : ""}[data-ds-typography="${typography}"]`;
152
151
  const layer = `ds.theme.typography.${typography}`;
153
152
  return {
153
+ usesDtcg: true,
154
154
  log: { verbosity: "silent" },
155
155
  preprocessors: ["tokens-studio"],
156
156
  platforms: {
@@ -167,10 +167,14 @@ const typographyCSS = ({ outPath, theme, typography }) => {
167
167
  destination: `typography/${typography}.css`,
168
168
  format: formats.typography.name,
169
169
  filter: (token) => {
170
- return typeEquals(
171
- ["typography", "fontweights", "fontfamilies", "lineheights", "fontsizes", "letterSpacing"],
170
+ const included = typeEquals(
171
+ ["typography", "fontweight", "fontFamily", "lineheight", "fontsize", "dimension", "font"],
172
+ token
173
+ );
174
+ return included && !pathStartsWithOneOf(
175
+ ["spacing", "sizing", "border-width", "border-radius", "theme", "theme2", "theme3", "theme4"],
172
176
  token
173
- ) && !(token.path[0] || "").startsWith("theme");
177
+ );
174
178
  }
175
179
  }
176
180
  ],
@@ -11,14 +11,15 @@ const colormode = {
11
11
  name: "ds/css-colormode",
12
12
  format: async ({ dictionary, file, options, platform }) => {
13
13
  const { allTokens } = dictionary;
14
- const { outputReferences } = options;
14
+ const { outputReferences, usesDtcg } = options;
15
15
  const { selector, mode, layer } = platform;
16
16
  const mode_ = mode;
17
17
  const header = await fileHeader({ file });
18
18
  const format = createPropertyFormatter({
19
19
  outputReferences,
20
20
  dictionary,
21
- format: "css"
21
+ format: "css",
22
+ usesDtcg
22
23
  });
23
24
  const colorSchemeProperty = mode_ === "dark" || mode_ === "light" ? `color-scheme: ${mode_};
24
25
  ` : "";
@@ -27,10 +28,12 @@ ${allTokens.map(format).join("\n")}
27
28
  ${colorSchemeProperty}}
28
29
  `;
29
30
  const autoSelectorContent = ["light", "dark"].includes(mode_) ? prefersColorScheme(mode_, content) : "";
30
- return header + `@layer ${layer} {
31
+ const body = R.isNotNil(layer) ? `@layer ${layer} {
31
32
  ${selector} ${content} ${autoSelectorContent}
32
33
  }
34
+ ` : `${selector} ${content} ${autoSelectorContent}
33
35
  `;
36
+ return header + body;
34
37
  }
35
38
  };
36
39
  const calculatedVariable = R.pipe(R.split(/:(.*?);/g), (split) => `${split[0]}: calc(${R.trim(split[1])});`);
@@ -38,13 +41,14 @@ const semantic = {
38
41
  name: "ds/css-semantic",
39
42
  format: async ({ dictionary, file, options, platform }) => {
40
43
  const { allTokens } = dictionary;
41
- const { outputReferences } = options;
44
+ const { outputReferences, usesDtcg } = options;
42
45
  const { selector, isCalculatedToken, layer } = platform;
43
46
  const header = await fileHeader({ file });
44
47
  const format = createPropertyFormatter({
45
48
  outputReferences,
46
49
  dictionary,
47
- format: "css"
50
+ format: "css",
51
+ usesDtcg
48
52
  });
49
53
  const formatTokens = R.map((token) => {
50
54
  const originalValue = getValue(token.original);
@@ -60,13 +64,15 @@ const semantic = {
60
64
  ${formattedVariables.join("\n")}
61
65
  }
62
66
  `;
63
- return header + `@layer ${layer} {
67
+ const body = R.isNotNil(layer) ? `@layer ${layer} {
64
68
  ${selector} ${content}
65
69
  }
70
+ ` : `${selector} ${content}
66
71
  `;
72
+ return header + body;
67
73
  }
68
74
  };
69
- const sortByType = R.sortBy((token) => token?.type === "typography");
75
+ const sortByType = R.sortBy((token) => token?.$type === "typography");
70
76
  const getVariableName = R.pipe(
71
77
  R.split(":"),
72
78
  R.head,
@@ -92,20 +98,21 @@ const sortTypographyLast = R.sortWith([
92
98
  const typography = {
93
99
  name: "ds/css-typography",
94
100
  format: async ({ dictionary, file, options, platform }) => {
95
- const { outputReferences } = options;
101
+ const { outputReferences, usesDtcg } = options;
96
102
  const { selector, layer } = platform;
97
103
  const header = await fileHeader({ file });
98
104
  const format = createPropertyFormatter({
99
105
  outputReferences,
100
106
  dictionary,
101
- format: "css"
107
+ format: "css",
108
+ usesDtcg
102
109
  });
103
110
  const sortedTokens = sortTypographyLast(dictionary.allTokens);
104
111
  const formattedTokens = R.pipe(
105
112
  sortByType,
106
113
  R.reduce(
107
114
  (acc, token) => {
108
- if (typeEquals("fontweights", token)) {
115
+ if (typeEquals("fontweight", token)) {
109
116
  const className = `
110
117
  .${classSelector(token)} {
111
118
  font-weight: ${getValue(token)};
@@ -116,7 +123,7 @@ const typography = {
116
123
  classes: [...acc.classes, className]
117
124
  };
118
125
  }
119
- if (typeEquals("lineheights", token)) {
126
+ if (typeEquals("lineheight", token)) {
120
127
  const className = `
121
128
  .${classSelector(token)} {
122
129
  line-height: ${getValue(token)};
@@ -128,21 +135,27 @@ const typography = {
128
135
  };
129
136
  }
130
137
  if (typeEquals("typography", token)) {
131
- const references = getReferences(getValue(token.original), dictionary.tokens);
132
- const fontweight = R.find(typeEquals(["fontweights"]))(references);
133
- const lineheight = R.find(typeEquals(["lineheights"]))(references);
134
- const fontsize = R.find(typeEquals(["fontsizes"]))(references);
135
- const letterSpacing = R.find(typeEquals(["letterSpacing"]))(references);
138
+ let references = [];
139
+ try {
140
+ references = getReferences(getValue(token.original), dictionary.tokens);
141
+ } catch (error) {
142
+ console.error("Error getting references", error);
143
+ throw new Error(JSON.stringify(token, null, 2));
144
+ }
145
+ const fontweight = R.find(typeEquals(["fontweight"]))(references);
146
+ const lineheight = R.find(typeEquals(["lineheight"]))(references);
147
+ const fontsize = R.find(typeEquals(["fontsize"]))(references);
148
+ const letterSpacing = R.find(typeEquals(["dimension"]))(references);
136
149
  const fontSizeVar = fontsize ? getVariableName(format(fontsize)) : null;
137
150
  const fontWeightVar = fontweight ? getVariableName(format(fontweight)) : null;
138
151
  const lineheightVar = lineheight ? getVariableName(format(lineheight)) : null;
139
152
  const letterSpacingVar = letterSpacing ? getVariableName(format(letterSpacing)) : null;
140
153
  const className = `
141
154
  .${classSelector(token)} {
142
- ${fontSizeVar && `font-size: ${fontSizeVar};`}
143
- ${lineheightVar && `line-height: ${lineheightVar};`}
144
- ${fontWeightVar && `font-weight: ${fontWeightVar};`}
145
- ${letterSpacingVar && `letter-spacing: ${letterSpacingVar};`}
155
+ ${fontSizeVar ? `font-size: ${fontSizeVar};` : ""}
156
+ ${lineheightVar ? `line-height: ${lineheightVar};` : ""}
157
+ ${fontWeightVar ? `font-weight: ${fontWeightVar};` : ""}
158
+ ${letterSpacingVar ? `letter-spacing: ${letterSpacingVar};` : ""}
146
159
  }`;
147
160
  return { ...acc, classes: [className, ...acc.classes] };
148
161
  }
@@ -157,10 +170,10 @@ const typography = {
157
170
  ${variables}
158
171
  ${classes}
159
172
  }` : classes;
160
- return header + `@layer ${layer} {
173
+ const body = R.isNotNil(layer) ? `@layer ${layer} {
161
174
  ${content}
162
- }
163
- `;
175
+ }` : content;
176
+ return header + body;
164
177
  }
165
178
  };
166
179
  export {
@@ -3,21 +3,25 @@ import { createPropertyFormatter, fileHeader } from "style-dictionary/utils";
3
3
  import { getType } from "../utils/utils.js";
4
4
  const groupByType = R.groupBy((token) => getType(token));
5
5
  const removeUnwatedTokens = R.filter(
6
- (token) => !["fds-base_spacing", "fds-base_sizing"].includes(token.name)
6
+ (token) => !["ds-base-spacing", "ds-base-sizing"].includes(token.name)
7
7
  );
8
+ const dissocExtensions = R.pipe(R.dissoc("$extensions"), R.dissocPath(["original", "$extensions"]));
9
+ const removeUnwatedProps = R.map((token) => dissocExtensions(token));
8
10
  const toCssVarName = R.pipe(R.split(":"), R.head, R.trim);
9
11
  const jsTokens = {
10
12
  name: "ds/js-tokens",
11
- format: async ({ dictionary, file }) => {
13
+ format: async ({ dictionary, file, options }) => {
14
+ const { usesDtcg } = options;
12
15
  const format = createPropertyFormatter({
13
16
  dictionary,
14
- format: "css"
17
+ format: "css",
18
+ usesDtcg
15
19
  });
16
20
  const formatTokens = R.map((token) => ({
17
21
  ...token,
18
22
  name: toCssVarName(format(token))
19
23
  }));
20
- const processTokens = R.pipe(removeUnwatedTokens, formatTokens, groupByType);
24
+ const processTokens = R.pipe(removeUnwatedTokens, removeUnwatedProps, formatTokens, groupByType);
21
25
  const tokens = processTokens(dictionary.allTokens);
22
26
  const content = Object.entries(tokens).map(
23
27
  ([name, token]) => `export const ${name} = ${JSON.stringify(token, null, 2).replace(/"([^"]+)":/g, "$1:")}
@@ -1,12 +1,16 @@
1
1
  import * as R from "ramda";
2
2
  import { noCase } from "./utils/noCase.js";
3
- import { getValue, typeEquals } from "./utils/utils.js";
3
+ import { getValue, pathStartsWithOneOf, typeEquals } from "./utils/utils.js";
4
4
  const isPx = R.test(/\b\d+px\b/g);
5
5
  const sizeRem = {
6
6
  name: "ds/size/toRem",
7
7
  type: "value",
8
8
  transitive: true,
9
- filter: (token) => typeEquals(["sizing", "spacing", "borderRadius", "fontsizes"], token),
9
+ filter: (token) => {
10
+ const hasWantedType = typeEquals(["dimension", "fontsize"], token);
11
+ const hasWantedPath = pathStartsWithOneOf(["spacing", "sizing", "border-radius", "font-size"], token);
12
+ return hasWantedType && hasWantedPath;
13
+ },
10
14
  transform: (token, config) => {
11
15
  const value = getValue(token);
12
16
  if (isPx(value)) {
@@ -34,7 +38,7 @@ const typographyShorthand = {
34
38
  name: "typography/shorthand",
35
39
  type: "value",
36
40
  transitive: true,
37
- filter: (token) => token.type === "typography",
41
+ filter: (token) => typeEquals("typography", token),
38
42
  transform: (token) => {
39
43
  const typography = getValue(token);
40
44
  return `${typography.fontWeight} ${typography.fontSize}/${typography.lineHeight} '${typography.fontFamily}'`;
@@ -0,0 +1,31 @@
1
+ import glob from "fast-glob";
2
+ import fs from "fs-extra";
3
+ import * as R from "ramda";
4
+ const sortLightmodeFirst = R.sortWith([R.descend(R.includes("light")), R.descend(R.includes("secondary"))]);
5
+ const header = `@charset "UTF-8";
6
+
7
+ @layer ds.reset, ds.theme, ds.base, ds.utilities, ds.components;
8
+
9
+ `;
10
+ const sortAndConcat = R.pipe(
11
+ sortLightmodeFirst,
12
+ R.map((file) => {
13
+ try {
14
+ const content = fs.readFileSync(file, "utf-8").toString();
15
+ return content;
16
+ } catch (e) {
17
+ console.error(`Error reading file: ${file}`);
18
+ return "";
19
+ }
20
+ }),
21
+ R.join("\n")
22
+ );
23
+ const makeEntryFile = async ({ outPath, buildPath, theme }) => {
24
+ const writePath = `${outPath}/${theme}.css`;
25
+ const files = await glob(`**/*`, { cwd: buildPath });
26
+ const content = header + sortAndConcat(files.map((file) => `${buildPath}/${file}`));
27
+ await fs.writeFile(writePath, content);
28
+ };
29
+ export {
30
+ makeEntryFile
31
+ };
@@ -8,7 +8,7 @@ function permutateThemes(themes, { separator = "-" } = {}) {
8
8
  return mapThemesToSetsObject(themes);
9
9
  }
10
10
  const groups = {};
11
- themes.forEach((theme) => {
11
+ for (const theme of themes) {
12
12
  if (theme.group) {
13
13
  groups[theme.group] = [...groups[theme.group] ?? [], theme];
14
14
  } else {
@@ -16,7 +16,7 @@ function permutateThemes(themes, { separator = "-" } = {}) {
16
16
  `Theme ${theme.name} does not have a group property, which is required for multi-dimensional theming.`
17
17
  );
18
18
  }
19
- });
19
+ }
20
20
  if (Object.keys(groups).length <= 1) {
21
21
  return mapThemesToSetsObject(themes);
22
22
  }
@@ -1,4 +1,6 @@
1
1
  import * as R from "ramda";
2
+ const mapToLowerCase = R.map(R.toLower);
3
+ const hasAnyTruth = R.any(R.equals(true));
2
4
  const getType = (token) => (token.$type ?? token.type) || "";
3
5
  const getValue = (token) => token.$value ?? token.value;
4
6
  const typeEquals = R.curry((types, token) => {
@@ -7,8 +9,17 @@ const typeEquals = R.curry((types, token) => {
7
9
  }
8
10
  return R.includes(R.toLower(getType(token)), R.map(R.toLower, Array.isArray(types) ? types : [types]));
9
11
  });
12
+ const pathStartsWithOneOf = R.curry((paths, token) => {
13
+ if (R.isNil(token)) {
14
+ return false;
15
+ }
16
+ const tokenPath = mapToLowerCase(token.path);
17
+ const matchPathsStartingWith = R.map((path) => R.startsWith([path], tokenPath), mapToLowerCase(paths));
18
+ return hasAnyTruth(matchPathsStartingWith);
19
+ });
10
20
  export {
11
21
  getType,
12
22
  getValue,
23
+ pathStartsWithOneOf,
13
24
  typeEquals
14
25
  };
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=designsystemet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"designsystemet.d.ts","sourceRoot":"","sources":["../../../bin/designsystemet.ts"],"names":[],"mappings":""}