@digdir/designsystemet 1.1.0 → 1.1.1

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  // bin/designsystemet.ts
4
4
  import { Argument, createCommand, program } from "@commander-js/extra-typings";
5
- import chalk10 from "chalk";
5
+ import chalk11 from "chalk";
6
6
  import * as R26 from "ramda";
7
7
 
8
8
  // src/colors/colorMetadata.ts
@@ -861,236 +861,15 @@ var migrations_default = {
861
861
 
862
862
  // src/tokens/build.ts
863
863
  import path from "path";
864
- import chalk6 from "chalk";
864
+ import chalk7 from "chalk";
865
865
  import * as R18 from "ramda";
866
866
 
867
- // src/tokens/process/output/tailwind.ts
868
- var createTailwindCSSFiles = (cssFiles) => {
869
- console.log("\n\u{1F371} Creating Tailwind Config");
870
- return cssFiles.map((file) => {
871
- if (file.destination) {
872
- const tailwindConfig = generateTailwind(file.output);
873
- const tailwindFile = {
874
- destination: file.destination.replace(".css", ".tailwind.css"),
875
- output: tailwindConfig
876
- };
877
- return tailwindFile;
878
- }
879
- return void 0;
880
- }).filter((item) => item !== void 0);
881
- };
882
- var generateTailwind = (css) => {
883
- const tailwind = ["--font-sans: var(--ds-font-family)"];
884
- const tokens = Array.from(new Set(css.match(/--ds-[^:)]+/g)), (m) => m).sort(
885
- (a, b) => a.localeCompare(b, void 0, { numeric: true, sensitivity: "base" })
886
- );
887
- for (const token of tokens) {
888
- if (token.startsWith("--ds-color-") && !token.startsWith("--ds-color-focus")) {
889
- tailwind.push(`--color-${token.replace("--ds-color-", "")}: var(${token})`);
890
- } else if (token.startsWith("--ds-font-weight-")) {
891
- tailwind.push(`--font-weight-${token.replace("--ds-font-weight-", "")}: var(${token})`);
892
- } else if (token.match(/--ds-border-radius-(sm|md|lg|xl)/)) {
893
- tailwind.push(`--radius-${token.replace("--ds-border-radius-", "")}: var(${token})`);
894
- } else if (token.match(/--ds-body-(sm|mg|lg)-body-font-size/)) {
895
- tailwind.push(`--text-${token.replace("--ds-body-", "").replace("-font-size", "")}: var(${token})`);
896
- } else if (token.match(/^--ds-size-\d+$/)) {
897
- tailwind.push(`--spacing-${token.replace("--ds-size-", "")}: var(${token})`);
898
- }
899
- }
900
- const dynamicColors = `[data-color] {
901
- --color-background-default: var(--ds-color-background-default);
902
- --color-background-tinted: var(--ds-color-background-tinted);
903
- --color-surface-default: var(--ds-color-surface-default);
904
- --color-surface-tinted: var(--ds-color-surface-tinted);
905
- --color-surface-hover: var(--ds-color-surface-hover);
906
- --color-surface-active: var(--ds-color-surface-active);
907
- --color-border-subtle: var(--ds-color-border-subtle);
908
- --color-border-default: var(--ds-color-border-default);
909
- --color-border-strong: var(--ds-color-border-strong);
910
- --color-text-subtle: var(--ds-color-text-subtle);
911
- --color-text-default: var(--ds-color-text-default);
912
- --color-base-default: var(--ds-color-base-default);
913
- --color-base-hover: var(--ds-color-base-hover);
914
- --color-base-active: var(--ds-color-base-active);
915
- --color-base-contrast-subtle: var(--ds-color-base-contrast-subtle);
916
- --color-base-contrast-default: var(--ds-color-base-contrast-default);
917
- }`;
918
- return `@theme {${tailwind.map((str) => `
919
- ${str};`).join("")}
920
- }
921
- ${dynamicColors}`;
922
- };
923
-
924
- // src/tokens/process/output/theme.ts
925
- import chalk3 from "chalk";
926
- import * as R5 from "ramda";
927
-
928
- // package.json
929
- var package_default = {
930
- name: "@digdir/designsystemet",
931
- version: "1.1.0",
932
- description: "CLI for Designsystemet",
933
- author: "Designsystemet team",
934
- engines: {
935
- node: ">=22.16.0"
936
- },
937
- repository: {
938
- type: "git",
939
- url: "git+https://github.com/digdir/designsystemet.git"
940
- },
941
- homepage: "https://github.com/digdir/designsystemet/tree/main/packages/cli",
942
- license: "MIT",
943
- type: "module",
944
- main: "./dist/src/index.js",
945
- files: [
946
- "./dist/**",
947
- "./configs/**"
948
- ],
949
- bin: "dist/bin/designsystemet.js",
950
- exports: {
951
- ".": {
952
- import: "./dist/src/index.js"
953
- },
954
- "./color": {
955
- import: "./dist/src/colors/index.js"
956
- },
957
- "./tokens": {
958
- import: "./dist/src/tokens/index.js"
959
- }
960
- },
961
- publishConfig: {
962
- access: "public"
963
- },
964
- scripts: {
965
- designsystemet: "tsx ./bin/designsystemet.ts",
966
- build: "tsup && pnpm build:types && pnpm build:json-schema",
967
- "build:types": "tsc --emitDeclarationOnly --declaration",
968
- "build:json-schema": "tsx ./src/scripts/createJsonSchema.ts",
969
- types: "tsc --noEmit",
970
- "test:tokens-create-options": 'pnpm run designsystemet tokens create -m dominant:"#007682" -n "#003333" -b 99 -o ./temp/options/design-tokens --theme options --clean',
971
- "test:tokens-create-config": "pnpm run designsystemet tokens create --config ./configs/test-tokens.config.json",
972
- "test:tokens-build": "pnpm run designsystemet tokens build -t ./temp/options/design-tokens -o ./temp/options/build --clean",
973
- "test:tokens-build-tailwind": "pnpm run designsystemet tokens build -t ./temp/options/design-tokens -o ./temp/options/build --clean --experimental-tailwind",
974
- "test:tokens-build-config": "pnpm run designsystemet tokens build -t ./temp/config/design-tokens -o ./temp/config/build --clean",
975
- "test:tokens-build-config-tailwind": "pnpm run designsystemet tokens build -t ./temp/config/design-tokens -o ./temp/config/build --clean --experimental-tailwind",
976
- "test:tokens-create-and-build-options": "pnpm test:tokens-create-options && pnpm test:tokens-build",
977
- "test:tokens-create-and-build-config": "pnpm test:tokens-create-config && pnpm test:tokens-build-config",
978
- test: "pnpm test:tokens-create-and-build-options && pnpm test:tokens-create-and-build-config",
979
- "digdir:tokens-build": "pnpm run designsystemet tokens build -t ../../internal/design-tokens -o ../../packages/theme/brand --clean --experimental-tailwind",
980
- "digdir:tokens-create": "pnpm run designsystemet tokens create --config ./configs/digdir.config.json",
981
- "update:template": "tsx ./src/scripts/update-template.ts",
982
- "update:theme-digdir": "pnpm digdir:tokens-create && tsx ./src/scripts/update-design-tokens.ts && pnpm digdir:tokens-build",
983
- verify: "pnpm test && pnpm update:template && pnpm update:theme-digdir && pnpm build:tokens"
984
- },
985
- dependencies: {
986
- "@commander-js/extra-typings": "^14.0.0",
987
- "@tokens-studio/sd-transforms": "1.3.0",
988
- "apca-w3": "^0.1.9",
989
- chalk: "^5.4.1",
990
- "change-case": "^5.4.4",
991
- "chroma-js": "^3.1.2",
992
- "colorjs.io": "^0.6.0-alpha.1",
993
- commander: "^13.1.0",
994
- "fast-glob": "^3.3.3",
995
- hsluv: "^1.0.1",
996
- "object-hash": "^3.0.0",
997
- postcss: "^8.5.5",
998
- ramda: "^0.30.1",
999
- "style-dictionary": "^4.4.0",
1000
- zod: "^3.25.64",
1001
- "zod-validation-error": "^3.5.0"
1002
- },
1003
- devDependencies: {
1004
- "@tokens-studio/types": "0.5.2",
1005
- "@types/apca-w3": "^0.1.3",
1006
- "@types/chroma-js": "^3.1.1",
1007
- "@types/fs-extra": "^11.0.4",
1008
- "@types/glob": "^8.1.0",
1009
- "@types/node": "^22.15.31",
1010
- "@types/object-hash": "^3.0.6",
1011
- "@types/ramda": "^0.30.2",
1012
- "fs-extra": "^11.3.0",
1013
- tslib: "^2.8.1",
1014
- tsup: "^8.5.0",
1015
- tsx: "^4.20.3",
1016
- typescript: "^5.8.3"
1017
- }
1018
- };
1019
-
1020
- // src/tokens/process/output/theme.ts
1021
- var defaultFileHeader = `build: v${package_default.version}`;
1022
- var createThemeCSSFiles = ({
1023
- processedBuilds,
1024
- fileHeader: fileHeader2 = defaultFileHeader
1025
- }) => {
1026
- const groupedByTheme = {};
1027
- for (const [_, buildResults] of Object.entries(R5.dissoc("types", processedBuilds))) {
1028
- for (const buildResult of buildResults) {
1029
- const themeName = buildResult.permutation.theme;
1030
- const newOutputs = buildResult.formatted;
1031
- if (R5.isNotEmpty(newOutputs)) {
1032
- const currentOutputs = groupedByTheme[themeName] ?? [];
1033
- groupedByTheme[themeName] = R5.concat(currentOutputs, newOutputs);
1034
- }
1035
- }
1036
- }
1037
- const sortOrder = [
1038
- "color-scheme/light",
1039
- "typography/secondary",
1040
- "semantic",
1041
- "color-scheme/dark",
1042
- "color-scheme/contrast",
1043
- "typography/primary",
1044
- "color/"
1045
- ];
1046
- const sortByDefinedOrder = R5.sortBy((file) => {
1047
- const filePath = file.destination || "";
1048
- const sortIndex = sortOrder.findIndex((sortElement) => {
1049
- if (sortElement.endsWith("/")) {
1050
- return filePath.includes(sortElement);
1051
- }
1052
- return filePath.includes(`${sortElement}.css`);
1053
- });
1054
- if (sortIndex === -1) {
1055
- console.error(
1056
- chalk3.yellow("WARNING: CSS section does not have a defined sort order:", filePath.replace(".css", ""))
1057
- );
1058
- console.log(
1059
- chalk3.dim(
1060
- `
1061
- The section will currently be added to the end of the entry file, but the exact
1062
- order may change due to nondeterminism.`.trim()
1063
- )
1064
- );
1065
- return Infinity;
1066
- }
1067
- return sortIndex;
1068
- });
1069
- const header = `@charset "UTF-8";
1070
- /*
1071
- ${fileHeader2}
1072
- */
1073
-
1074
- `;
1075
- const sortAlphabetically = R5.sort(R5.ascend((x) => x.destination || ""));
1076
- const pickOutputs = R5.map(R5.view(R5.lensProp("output")));
1077
- const themeCSSFile = R5.pipe(
1078
- sortAlphabetically,
1079
- sortByDefinedOrder,
1080
- pickOutputs,
1081
- R5.join("\n"),
1082
- (content) => header + content
1083
- );
1084
- const themeCSSFiles = Object.entries(groupedByTheme).map(([theme, files]) => ({
1085
- destination: `${theme}.css`,
1086
- output: themeCSSFile(files)
1087
- }));
1088
- return themeCSSFiles;
1089
- };
867
+ // src/tokens/process/output/declarations.ts
868
+ import chalk5 from "chalk";
1090
869
 
1091
870
  // src/tokens/process/platform.ts
1092
- import chalk5 from "chalk";
1093
- import * as R17 from "ramda";
871
+ import chalk4 from "chalk";
872
+ import * as R16 from "ramda";
1094
873
  import StyleDictionary2 from "style-dictionary";
1095
874
 
1096
875
  // src/tokens/types.ts
@@ -1101,30 +880,30 @@ var colorCategories = {
1101
880
 
1102
881
  // src/tokens/process/configs.ts
1103
882
  import { register } from "@tokens-studio/sd-transforms";
1104
- import * as R16 from "ramda";
883
+ import * as R15 from "ramda";
1105
884
  import StyleDictionary from "style-dictionary";
1106
885
 
1107
886
  // src/tokens/utils.ts
1108
- import * as R6 from "ramda";
1109
- var mapToLowerCase = R6.map(R6.toLower);
1110
- var hasAnyTruth = R6.any(R6.equals(true));
887
+ import * as R5 from "ramda";
888
+ var mapToLowerCase = R5.map(R5.toLower);
889
+ var hasAnyTruth = R5.any(R5.equals(true));
1111
890
  var getType = (token) => (token.$type ?? token.type) || "";
1112
891
  var getValue = (token) => token.$value ?? token.value;
1113
- var typeEquals = R6.curry(
892
+ var typeEquals = R5.curry(
1114
893
  (types, token) => {
1115
- if (R6.isNil(token)) {
894
+ if (R5.isNil(token)) {
1116
895
  return false;
1117
896
  }
1118
- return R6.includes(R6.toLower(getType(token)), R6.map(R6.toLower, Array.isArray(types) ? types : [types]));
897
+ return R5.includes(R5.toLower(getType(token)), R5.map(R5.toLower, Array.isArray(types) ? types : [types]));
1119
898
  }
1120
899
  );
1121
- var pathStartsWithOneOf = R6.curry(
900
+ var pathStartsWithOneOf = R5.curry(
1122
901
  (paths, token) => {
1123
- if (R6.isNil(token)) {
902
+ if (R5.isNil(token)) {
1124
903
  return false;
1125
904
  }
1126
905
  const tokenPath = mapToLowerCase(token.path);
1127
- const matchPathsStartingWith = R6.map((path5) => R6.startsWith([path5], tokenPath), mapToLowerCase(paths));
906
+ const matchPathsStartingWith = R5.map((path5) => R5.startsWith([path5], tokenPath), mapToLowerCase(paths));
1128
907
  return hasAnyTruth(matchPathsStartingWith);
1129
908
  }
1130
909
  );
@@ -1132,7 +911,7 @@ function isSemanticToken(token) {
1132
911
  return token.filePath.includes("semantic/");
1133
912
  }
1134
913
  function isSemanticColorToken(token, color) {
1135
- return token.filePath.includes("semantic/") && R6.startsWith(["color", color], token.path);
914
+ return token.filePath.includes("semantic/") && R5.startsWith(["color", color], token.path);
1136
915
  }
1137
916
  function isGlobalColorToken(token) {
1138
917
  return typeEquals("color", token) && pathStartsWithOneOf(["global"], token);
@@ -1143,7 +922,7 @@ function isColorCategoryToken(token, category) {
1143
922
  (colorCategory2) => isColorCategoryToken(token, colorCategory2)
1144
923
  );
1145
924
  }
1146
- return R6.startsWith(["color", category], token.path);
925
+ return R5.startsWith(["color", category], token.path);
1147
926
  }
1148
927
  var isDigit = (s) => /^\d+$/.test(s);
1149
928
  function traverseObj(obj, fn) {
@@ -1159,7 +938,7 @@ function traverseObj(obj, fn) {
1159
938
  return obj;
1160
939
  }
1161
940
  function inlineTokens(shouldInline, tokens) {
1162
- const [inlineableTokens, otherTokens] = R6.partition(shouldInline, tokens);
941
+ const [inlineableTokens, otherTokens] = R5.partition(shouldInline, tokens);
1163
942
  return otherTokens.map((token) => {
1164
943
  let transformed = getValue(token.original);
1165
944
  for (const ref of inlineableTokens) {
@@ -1168,16 +947,16 @@ function inlineTokens(shouldInline, tokens) {
1168
947
  transformed = transformed.replaceAll(`{${refName}}`, getValue(ref.original));
1169
948
  }
1170
949
  }
1171
- const tokenWithInlinedRefs = R6.set(R6.lensPath(["original", "$value"]), transformed, token);
950
+ const tokenWithInlinedRefs = R5.set(R5.lensPath(["original", "$value"]), transformed, token);
1172
951
  return tokenWithInlinedRefs;
1173
952
  });
1174
953
  }
1175
954
 
1176
955
  // src/tokens/process/configs/color.ts
1177
- import * as R11 from "ramda";
956
+ import * as R10 from "ramda";
1178
957
 
1179
958
  // src/tokens/process/formats/css/color.ts
1180
- import * as R7 from "ramda";
959
+ import * as R6 from "ramda";
1181
960
  import { createPropertyFormatter } from "style-dictionary/utils";
1182
961
  var prefersColorScheme = (colorScheme2, content) => `
1183
962
  @media (prefers-color-scheme: ${colorScheme2}) {
@@ -1201,8 +980,8 @@ var colorScheme = {
1201
980
  color-scheme: ${colorScheme_};
1202
981
  ` : "";
1203
982
  const filteredAllTokens = allTokens.filter(
1204
- R7.allPass([
1205
- R7.anyPass([
983
+ R6.allPass([
984
+ R6.anyPass([
1206
985
  // Include semantic tokens in the output
1207
986
  isSemanticToken,
1208
987
  // Include global color tokens
@@ -1218,7 +997,7 @@ ${formattedTokens}
1218
997
  ${colorSchemeProperty}}
1219
998
  `;
1220
999
  const autoSelectorContent = ["light", "dark"].includes(colorScheme_) ? prefersColorScheme(colorScheme_, content) : "";
1221
- const body = R7.isNotNil(layer) ? `@layer ${layer} {
1000
+ const body = R6.isNotNil(layer) ? `@layer ${layer} {
1222
1001
  ${selector} ${content} ${autoSelectorContent}
1223
1002
  }
1224
1003
  ` : `${selector} ${content} ${autoSelectorContent}
@@ -1231,7 +1010,7 @@ var colorCategory = {
1231
1010
  format: async ({ dictionary, options, platform }) => {
1232
1011
  const { outputReferences, usesDtcg } = options;
1233
1012
  const { selector, layer } = platform;
1234
- const format = R7.compose(
1013
+ const format = R6.compose(
1235
1014
  createPropertyFormatter({
1236
1015
  outputReferences,
1237
1016
  dictionary,
@@ -1252,7 +1031,7 @@ var colorCategory = {
1252
1031
  ${formattedTokens}
1253
1032
  }
1254
1033
  `;
1255
- const body = R7.isNotNil(layer) ? `@layer ${layer} {
1034
+ const body = R6.isNotNil(layer) ? `@layer ${layer} {
1256
1035
  ${selector} ${content}
1257
1036
  }
1258
1037
  ` : `${selector} ${content}
@@ -1262,12 +1041,12 @@ ${selector} ${content}
1262
1041
  };
1263
1042
 
1264
1043
  // src/tokens/process/formats/css/semantic.ts
1265
- import * as R8 from "ramda";
1044
+ import * as R7 from "ramda";
1266
1045
  import { createPropertyFormatter as createPropertyFormatter2 } from "style-dictionary/utils";
1267
1046
  var isNumericBorderRadiusToken = (t) => t.path[0] === "border-radius" && isDigit(t.path[1]);
1268
1047
  var isNumericSizeToken = (t) => pathStartsWithOneOf(["size"], t) && isDigit(t.path[1]);
1269
1048
  var isSizeToken = (t) => pathStartsWithOneOf(["size"], t);
1270
- var isInlineTokens = R8.anyPass([isNumericBorderRadiusToken, isNumericSizeToken, isSizeToken]);
1049
+ var isInlineTokens = R7.anyPass([isNumericBorderRadiusToken, isNumericSizeToken, isSizeToken]);
1271
1050
  var overrideSizingFormula = (format, token) => {
1272
1051
  const [name, value] = format(token).split(":");
1273
1052
  const calc = value.replace(`var(--ds-size-mode-font-size)`, "1em").replace(/floor\((.*)\);/, "calc($1)");
@@ -1279,7 +1058,7 @@ var overrideSizingFormula = (format, token) => {
1279
1058
  };
1280
1059
  };
1281
1060
  var formatSizingTokens = (format, tokens) => {
1282
- const { round, calc } = R8.reduce(
1061
+ const { round, calc } = R7.reduce(
1283
1062
  (acc, token) => {
1284
1063
  const { round: round2, calc: calc2, name } = overrideSizingFormula(format, token);
1285
1064
  return {
@@ -1309,17 +1088,17 @@ var semantic = {
1309
1088
  usesDtcg
1310
1089
  });
1311
1090
  const tokens = inlineTokens(isInlineTokens, dictionary.allTokens);
1312
- const filteredTokens = R8.reject((token) => token.name.includes("ds-size-mode-font-size"), tokens);
1313
- const [sizingTokens, restTokens] = R8.partition(
1091
+ const filteredTokens = R7.reject((token) => token.name.includes("ds-size-mode-font-size"), tokens);
1092
+ const [sizingTokens, restTokens] = R7.partition(
1314
1093
  (t) => pathStartsWithOneOf(["_size"], t) && isDigit(t.path[1]),
1315
1094
  filteredTokens
1316
1095
  );
1317
- const formattedTokens = [R8.map(format, restTokens).join("\n"), formatSizingTokens(format, sizingTokens)];
1096
+ const formattedTokens = [R7.map(format, restTokens).join("\n"), formatSizingTokens(format, sizingTokens)];
1318
1097
  const content = `{
1319
1098
  ${formattedTokens.join("\n")}
1320
1099
  }
1321
1100
  `;
1322
- const body = R8.isNotNil(layer) ? `@layer ${layer} {
1101
+ const body = R7.isNotNil(layer) ? `@layer ${layer} {
1323
1102
  ${selector} ${content}
1324
1103
  }
1325
1104
  ` : `${selector} ${content}
@@ -1329,11 +1108,11 @@ ${selector} ${content}
1329
1108
  };
1330
1109
 
1331
1110
  // src/tokens/process/formats/css/typography.ts
1332
- import * as R9 from "ramda";
1111
+ import * as R8 from "ramda";
1333
1112
  import { createPropertyFormatter as createPropertyFormatter3 } from "style-dictionary/utils";
1334
- var typographyFontFamilyPredicate = R9.allPass([
1335
- R9.pathSatisfies(R9.includes("typography"), ["path"]),
1336
- R9.pathSatisfies(R9.includes("fontFamily"), ["path"])
1113
+ var typographyFontFamilyPredicate = R8.allPass([
1114
+ R8.pathSatisfies(R8.includes("typography"), ["path"]),
1115
+ R8.pathSatisfies(R8.includes("fontFamily"), ["path"])
1337
1116
  ]);
1338
1117
  var typography = {
1339
1118
  name: "ds/css-typography",
@@ -1346,12 +1125,12 @@ var typography = {
1346
1125
  format: "css",
1347
1126
  usesDtcg
1348
1127
  });
1349
- const filteredTokens = R9.reject(typographyFontFamilyPredicate, dictionary.allTokens);
1350
- const formattedTokens = R9.pipe(R9.map(format), R9.join("\n"))(filteredTokens);
1128
+ const filteredTokens = R8.reject(typographyFontFamilyPredicate, dictionary.allTokens);
1129
+ const formattedTokens = R8.pipe(R8.map(format), R8.join("\n"))(filteredTokens);
1351
1130
  const content = selector ? `${selector} {
1352
1131
  ${formattedTokens}
1353
1132
  }` : formattedTokens;
1354
- const body = R9.isNotNil(layer) ? `@layer ${layer} {
1133
+ const body = R8.isNotNil(layer) ? `@layer ${layer} {
1355
1134
  ${content}
1356
1135
  }` : content;
1357
1136
  return body;
@@ -1368,8 +1147,8 @@ var formats = {
1368
1147
 
1369
1148
  // src/tokens/process/transformers.ts
1370
1149
  import { checkAndEvaluateMath } from "@tokens-studio/sd-transforms";
1371
- import * as R10 from "ramda";
1372
- var isPx = R10.test(/\b\d+px\b/g);
1150
+ import * as R9 from "ramda";
1151
+ var isPx = R9.test(/\b\d+px\b/g);
1373
1152
  var sizeRem = {
1374
1153
  name: "ds/size/toRem",
1375
1154
  type: "value",
@@ -1459,7 +1238,7 @@ var colorSchemeVariables = ({ "color-scheme": colorScheme2 = "light", theme }) =
1459
1238
  {
1460
1239
  destination: `color-scheme/${colorScheme2}.css`,
1461
1240
  format: formats.colorScheme.name,
1462
- filter: (token) => typeEquals("color", token) && !R11.startsWith(["global"], token.path)
1241
+ filter: (token) => typeEquals("color", token) && !R10.startsWith(["global"], token.path)
1463
1242
  }
1464
1243
  ],
1465
1244
  options: {
@@ -1510,7 +1289,7 @@ var colorCategoryVariables = (opts) => ({ "color-scheme": colorScheme2, theme, .
1510
1289
  };
1511
1290
 
1512
1291
  // src/tokens/process/configs/semantic.ts
1513
- import * as R12 from "ramda";
1292
+ import * as R11 from "ramda";
1514
1293
  import { outputReferencesFilter } from "style-dictionary/utils";
1515
1294
  var semanticVariables = ({ theme }) => {
1516
1295
  const selector = `:root`;
@@ -1533,8 +1312,8 @@ var semanticVariables = ({ theme }) => {
1533
1312
  destination: `semantic.css`,
1534
1313
  format: formats.semantic.name,
1535
1314
  filter: (token) => {
1536
- const isUwantedToken = R12.anyPass([R12.includes("primitives/global")])(token.filePath);
1537
- const isPrivateToken = R12.includes("_", token.path);
1315
+ const isUwantedToken = R11.anyPass([R11.includes("primitives/global")])(token.filePath);
1316
+ const isPrivateToken = R11.includes("_", token.path);
1538
1317
  const unwantedPaths = pathStartsWithOneOf(["font-size", "line-height", "letter-spacing"], token);
1539
1318
  const unwantedTypes = typeEquals(["color", "fontWeight", "fontFamily", "typography"], token);
1540
1319
  const unwantedTokens = !(unwantedPaths || unwantedTypes || isPrivateToken || isUwantedToken);
@@ -1555,20 +1334,20 @@ var semanticVariables = ({ theme }) => {
1555
1334
  };
1556
1335
 
1557
1336
  // src/tokens/process/configs/storefront.ts
1558
- import * as R14 from "ramda";
1337
+ import * as R13 from "ramda";
1559
1338
  import { outputReferencesFilter as outputReferencesFilter2 } from "style-dictionary/utils";
1560
1339
 
1561
1340
  // src/tokens/process/formats/js-tokens.ts
1562
- import * as R13 from "ramda";
1341
+ import * as R12 from "ramda";
1563
1342
  import { createPropertyFormatter as createPropertyFormatter4, fileHeader } from "style-dictionary/utils";
1564
- var groupByType = R13.groupBy((token) => getType(token));
1565
- var removeUnwatedTokens = R13.pipe(
1566
- R13.reject((token) => isColorCategoryToken(token)),
1567
- R13.reject((token) => R13.any((path5) => path5.startsWith("_"))(token.path))
1343
+ var groupByType = R12.groupBy((token) => getType(token));
1344
+ var removeUnwatedTokens = R12.pipe(
1345
+ R12.reject((token) => isColorCategoryToken(token)),
1346
+ R12.reject((token) => R12.any((path5) => path5.startsWith("_"))(token.path))
1568
1347
  );
1569
- var dissocExtensions = R13.pipe(R13.dissoc("$extensions"), R13.dissocPath(["original", "$extensions"]));
1570
- var removeUnwatedProps = R13.map((token) => dissocExtensions(token));
1571
- var toCssVarName = R13.pipe(R13.split(":"), R13.head, R13.trim);
1348
+ var dissocExtensions = R12.pipe(R12.dissoc("$extensions"), R12.dissocPath(["original", "$extensions"]));
1349
+ var removeUnwatedProps = R12.map((token) => dissocExtensions(token));
1350
+ var toCssVarName = R12.pipe(R12.split(":"), R12.head, R12.trim);
1572
1351
  var jsTokens = {
1573
1352
  name: "ds/js-tokens",
1574
1353
  format: async ({ dictionary, file, options }) => {
@@ -1579,7 +1358,7 @@ var jsTokens = {
1579
1358
  format: "css",
1580
1359
  usesDtcg
1581
1360
  });
1582
- const formatTokens = R13.map((token) => {
1361
+ const formatTokens = R12.map((token) => {
1583
1362
  if (pathStartsWithOneOf(["size", "_size"], token)) {
1584
1363
  const { calc, name } = overrideSizingFormula(format, token);
1585
1364
  return {
@@ -1593,7 +1372,7 @@ var jsTokens = {
1593
1372
  name: toCssVarName(format(token))
1594
1373
  };
1595
1374
  });
1596
- const processTokens = R13.pipe(removeUnwatedTokens, removeUnwatedProps, formatTokens, groupByType);
1375
+ const processTokens = R12.pipe(removeUnwatedTokens, removeUnwatedProps, formatTokens, groupByType);
1597
1376
  const tokens = processTokens(inlineTokens(isInlineTokens, dictionary.allTokens));
1598
1377
  const content = Object.entries(tokens).map(
1599
1378
  ([name, token]) => `export const ${name} = ${JSON.stringify(token, null, 2).replace(/"([^"]+)":/g, "$1:")}
@@ -1618,9 +1397,9 @@ var typescriptTokens = ({ "color-scheme": colorScheme2, theme }) => {
1618
1397
  destination: `${colorScheme2}.ts`,
1619
1398
  format: jsTokens.name,
1620
1399
  filter: (token) => {
1621
- if (pathStartsWithOneOf(["border-width", "letter-spacing", "border-radius"], token) && !R14.includes("semantic", token.filePath))
1400
+ if (pathStartsWithOneOf(["border-width", "letter-spacing", "border-radius"], token) && !R13.includes("semantic", token.filePath))
1622
1401
  return false;
1623
- const isSemanticColor = R14.includes("semantic", token.filePath) && typeEquals(["color"], token);
1402
+ const isSemanticColor = R13.includes("semantic", token.filePath) && typeEquals(["color"], token);
1624
1403
  const wantedTypes = typeEquals(["shadow", "dimension", "typography", "opacity"], token);
1625
1404
  return isSemanticColor || wantedTypes;
1626
1405
  }
@@ -1849,19 +1628,19 @@ var TypographyValues;
1849
1628
  })(TypographyValues || (TypographyValues = {}));
1850
1629
 
1851
1630
  // src/tokens/process/utils/getMultidimensionalThemes.ts
1852
- import chalk4 from "chalk";
1631
+ import chalk3 from "chalk";
1853
1632
  import { kebabCase } from "change-case";
1854
- import * as R15 from "ramda";
1633
+ import * as R14 from "ramda";
1855
1634
  var getMultidimensionalThemes = (processed$themes, dimensions) => {
1856
1635
  const verboseLogging = buildOptions?.verbose;
1857
1636
  const grouped$themes = groupThemes(processed$themes);
1858
1637
  const permutations = permutateThemes(grouped$themes);
1859
1638
  const ALL_DEPENDENT_ON = ["theme"];
1860
- const keys3 = R15.keys(grouped$themes);
1639
+ const keys3 = R14.keys(grouped$themes);
1861
1640
  const nonDependentKeys = keys3.filter((x) => ![...ALL_DEPENDENT_ON, ...dimensions].includes(x));
1862
1641
  if (verboseLogging) {
1863
- console.log(chalk4.cyan(`\u{1F50E} Finding theme permutations for ${dimensions}`));
1864
- console.log(chalk4.cyan(` (ignoring permutations for ${nonDependentKeys})`));
1642
+ console.log(chalk3.cyan(`\u{1F50E} Finding theme permutations for ${dimensions}`));
1643
+ console.log(chalk3.cyan(` (ignoring permutations for ${nonDependentKeys})`));
1865
1644
  }
1866
1645
  return permutations.filter((val) => {
1867
1646
  const filters = nonDependentKeys.map((x) => val.permutation[x] === grouped$themes[x][0].name);
@@ -1897,7 +1676,7 @@ function groupThemes(themes) {
1897
1676
  }
1898
1677
  return groups;
1899
1678
  }
1900
- var hasUnknownProps = R15.pipe(R15.values, R15.none(R15.equals("unknown")), R15.not);
1679
+ var hasUnknownProps = R14.pipe(R14.values, R14.none(R14.equals("unknown")), R14.not);
1901
1680
  function permutateThemes(groups) {
1902
1681
  const separator = "_";
1903
1682
  const permutations = cartesian(Object.values(groups));
@@ -1907,8 +1686,8 @@ function permutateThemes(groups) {
1907
1686
  const { group, name, selectedTokenSets } = theme;
1908
1687
  let updatedPermutation = acc.permutation;
1909
1688
  if (group) {
1910
- const groupProp = R15.lensProp(group);
1911
- updatedPermutation = R15.set(groupProp, name, updatedPermutation);
1689
+ const groupProp = R14.lensProp(group);
1690
+ updatedPermutation = R14.set(groupProp, name, updatedPermutation);
1912
1691
  }
1913
1692
  const updatedName = `${String(acc.name)}${acc ? separator : ""}${name}`;
1914
1693
  const sets = [...acc.selectedTokenSets, ...filterTokenSets(selectedTokenSets)];
@@ -1954,6 +1733,12 @@ function filterTokenSets(tokensets) {
1954
1733
  function cartesian(a) {
1955
1734
  return a.reduce((a2, b) => a2.flatMap((d) => b.map((e) => [d, e].flat())));
1956
1735
  }
1736
+ var getCustomColors = (processed$themes, colorGroups) => processed$themes.filter((x) => {
1737
+ if (!x.group) {
1738
+ return false;
1739
+ }
1740
+ return colorGroups.includes(x.group);
1741
+ }).map((x) => x.name);
1957
1742
 
1958
1743
  // src/tokens/process/configs.ts
1959
1744
  void register(StyleDictionary, { withSDBuiltins: false });
@@ -1992,7 +1777,7 @@ var getConfigsForThemeDimensions = (getConfig, processed$themes, dimensions, opt
1992
1777
  obj.filePath = tokenSet;
1993
1778
  }
1994
1779
  });
1995
- tokenSource.tokens = R16.mergeDeepRight(tokenSource.tokens, tokensWithFilePath);
1780
+ tokenSource.tokens = R15.mergeDeepRight(tokenSource.tokens, tokensWithFilePath);
1996
1781
  }
1997
1782
  }
1998
1783
  } else {
@@ -2036,12 +1821,6 @@ var initResult = {
2036
1821
  };
2037
1822
  var buildOptions;
2038
1823
  var sd = new StyleDictionary2();
2039
- var getCustomColors = (processed$themes, colorGroups) => processed$themes.filter((x) => {
2040
- if (!x.group) {
2041
- return false;
2042
- }
2043
- return colorGroups.includes(x.group);
2044
- }).map((x) => x.name);
2045
1824
  var buildConfigs = {
2046
1825
  typography: { getConfig: configs.typographyVariables, dimensions: ["typography"] },
2047
1826
  "color-scheme": { getConfig: configs.colorSchemeVariables, dimensions: ["color-scheme"] },
@@ -2082,46 +1861,54 @@ var buildConfigs = {
2082
1861
  // },
2083
1862
  };
2084
1863
  async function processPlatform(options) {
2085
- const { type, $themes } = options;
1864
+ const { type, processed$themes } = options;
2086
1865
  const platform = "css";
2087
1866
  const tokenSets = type === "format" ? options.tokenSets : void 0;
2088
1867
  const tokensDir = type === "build" ? options.tokensDir : void 0;
2089
1868
  const UNSAFE_DEFAULT_COLOR = process.env.UNSAFE_DEFAULT_COLOR ?? "";
2090
1869
  if (UNSAFE_DEFAULT_COLOR) {
2091
1870
  console.warn(
2092
- chalk5.yellow(
1871
+ chalk4.yellow(
2093
1872
  `
2094
- \u26A0\uFE0F UNSAFE_DEFAULT_COLOR is set to ${chalk5.blue(UNSAFE_DEFAULT_COLOR)}. This will override the default color.`
1873
+ \u26A0\uFE0F UNSAFE_DEFAULT_COLOR is set to ${chalk4.blue(UNSAFE_DEFAULT_COLOR)}. This will override the default color.`
2095
1874
  )
2096
1875
  );
2097
1876
  }
2098
1877
  const UNSAFE_COLOR_GROUPS = Array.from(process.env.UNSAFE_COLOR_GROUPS?.split(",") ?? []);
2099
1878
  if (UNSAFE_COLOR_GROUPS.length > 0) {
2100
1879
  console.warn(
2101
- chalk5.yellow(
1880
+ chalk4.yellow(
2102
1881
  `
2103
- \u26A0\uFE0F UNSAFE_COLOR_GROUPS is set to ${chalk5.blue(`[${UNSAFE_COLOR_GROUPS.join(", ")}]`)}. This will override the default color groups.`
1882
+ \u26A0\uFE0F UNSAFE_COLOR_GROUPS is set to ${chalk4.blue(`[${UNSAFE_COLOR_GROUPS.join(", ")}]`)}. This will override the default color groups.`
2104
1883
  )
2105
1884
  );
2106
1885
  }
2107
1886
  const colorGroups = UNSAFE_COLOR_GROUPS.length > 0 ? UNSAFE_COLOR_GROUPS : [colorCategories.main, colorCategories.support].map((c) => `${c}-color`);
2108
1887
  buildOptions = options;
2109
1888
  buildOptions.defaultColor = UNSAFE_DEFAULT_COLOR;
2110
- const processed$themes = $themes.map(processThemeObject).filter((theme) => R17.not(theme.group === "size" && theme.name !== "medium"));
2111
- const customColors = getCustomColors(processed$themes, colorGroups);
1889
+ buildOptions.colorGroups = colorGroups;
1890
+ const filteredProcessed$themes = processed$themes.filter(
1891
+ (theme) => R16.not(theme.group === "size" && theme.name !== "medium")
1892
+ );
1893
+ const customColors = getCustomColors(filteredProcessed$themes, colorGroups);
2112
1894
  if (!buildOptions.defaultColor) {
2113
- const firstMainColor = R17.head(customColors);
1895
+ const firstMainColor = R16.head(customColors);
2114
1896
  buildOptions.defaultColor = firstMainColor;
2115
1897
  }
2116
1898
  if (buildOptions.defaultColor) {
2117
1899
  console.log(`
2118
- \u{1F3A8} Using ${chalk5.blue(buildOptions.defaultColor)} as default color`);
1900
+ \u{1F3A8} Using ${chalk4.blue(buildOptions.defaultColor)} as default color`);
2119
1901
  }
2120
- const buildAndSdConfigs = R17.map((buildConfig) => {
2121
- const sdConfigs = getConfigsForThemeDimensions(buildConfig.getConfig, processed$themes, buildConfig.dimensions, {
2122
- tokensDir,
2123
- tokenSets
2124
- });
1902
+ const buildAndSdConfigs = R16.map((buildConfig) => {
1903
+ const sdConfigs = getConfigsForThemeDimensions(
1904
+ buildConfig.getConfig,
1905
+ filteredProcessed$themes,
1906
+ buildConfig.dimensions,
1907
+ {
1908
+ tokensDir,
1909
+ tokenSets
1910
+ }
1911
+ );
2125
1912
  const unknownConfigs = buildConfig.dimensions.map(
2126
1913
  (dimension) => sdConfigs.filter((x) => x.permutation[dimension] === "unknown")
2127
1914
  );
@@ -2145,23 +1932,22 @@ async function processPlatform(options) {
2145
1932
  "warning-color": [initResult],
2146
1933
  "info-color": [initResult],
2147
1934
  semantic: [initResult],
2148
- typography: [initResult],
2149
- types: [initResult]
1935
+ typography: [initResult]
2150
1936
  };
2151
1937
  try {
2152
- for (const [buildName, { buildConfig, sdConfigs }] of R17.toPairs(buildAndSdConfigs)) {
1938
+ for (const [buildName, { buildConfig, sdConfigs }] of R16.toPairs(buildAndSdConfigs)) {
2153
1939
  if (!(buildConfig.enabled?.() ?? true)) {
2154
1940
  continue;
2155
1941
  }
2156
1942
  if (sdConfigs.length > 0) {
2157
1943
  console.log(`
2158
- \u{1F371} Building ${chalk5.green(buildConfig.name ?? buildName)}`);
1944
+ \u{1F371} Building ${chalk4.green(buildConfig.name ?? buildName)}`);
2159
1945
  const results = await Promise.all(
2160
1946
  sdConfigs.map(async (sdConfig) => {
2161
1947
  const { config, permutation } = sdConfig;
2162
1948
  const modes = ["theme", ...buildConfig.dimensions];
2163
1949
  const modeMessage = modes.map((x) => permutation[x]).join(" - ");
2164
- const logMessage = R17.isNil(buildConfig.log) ? modeMessage : buildConfig?.log(sdConfig);
1950
+ const logMessage = R16.isNil(buildConfig.log) ? modeMessage : buildConfig?.log(sdConfig);
2165
1951
  console.log(logMessage);
2166
1952
  const sdOptions = { cache: true };
2167
1953
  const sdExtended = await sd.extend(config);
@@ -2181,17 +1967,22 @@ async function processPlatform(options) {
2181
1967
  }
2182
1968
  throw err;
2183
1969
  }
2184
- const colorsFileName = "colors.d.ts";
2185
- const reactColorTypes = await createColorTypeDeclaration(customColors);
2186
- processedBuilds.types = [
1970
+ return processedBuilds;
1971
+ }
1972
+
1973
+ // src/tokens/process/output/declarations.ts
1974
+ var createTypeDeclarationFiles = (processed$themes) => {
1975
+ const colorGroups = buildOptions?.colorGroups || [];
1976
+ const customColors = getCustomColors(processed$themes, colorGroups);
1977
+ const typeDeclaration = createColorTypeDeclaration(customColors);
1978
+ return [
2187
1979
  {
2188
- ...initResult,
2189
- formatted: [{ output: reactColorTypes, destination: colorsFileName }]
1980
+ output: typeDeclaration,
1981
+ destination: "colors.d.ts"
2190
1982
  }
2191
1983
  ];
2192
- return processedBuilds;
2193
- }
2194
- async function createColorTypeDeclaration(colors2) {
1984
+ };
1985
+ function createColorTypeDeclaration(colors2) {
2195
1986
  console.log(`
2196
1987
  \u{1F371} Building ${chalk5.green("type declarations")}`);
2197
1988
  const typeDeclaration = `
@@ -2206,6 +1997,232 @@ ${colors2.map((color) => ` ${color}: never;`).join("\n")}
2206
1997
  return typeDeclaration;
2207
1998
  }
2208
1999
 
2000
+ // src/tokens/process/output/tailwind.ts
2001
+ var createTailwindCSSFiles = (cssFiles) => {
2002
+ console.log("\n\u{1F371} Creating Tailwind Config");
2003
+ return cssFiles.map((file) => {
2004
+ if (file.destination) {
2005
+ const tailwindConfig = generateTailwind(file.output);
2006
+ const tailwindFile = {
2007
+ destination: file.destination.replace(".css", ".tailwind.css"),
2008
+ output: tailwindConfig
2009
+ };
2010
+ return tailwindFile;
2011
+ }
2012
+ return void 0;
2013
+ }).filter((item) => item !== void 0);
2014
+ };
2015
+ var generateTailwind = (css) => {
2016
+ const tailwind = ["--font-sans: var(--ds-font-family)"];
2017
+ const tokens = Array.from(new Set(css.match(/--ds-[^:)]+/g)), (m) => m).sort(
2018
+ (a, b) => a.localeCompare(b, void 0, { numeric: true, sensitivity: "base" })
2019
+ );
2020
+ for (const token of tokens) {
2021
+ if (token.startsWith("--ds-color-") && !token.startsWith("--ds-color-focus")) {
2022
+ tailwind.push(`--color-${token.replace("--ds-color-", "")}: var(${token})`);
2023
+ } else if (token.startsWith("--ds-font-weight-")) {
2024
+ tailwind.push(`--font-weight-${token.replace("--ds-font-weight-", "")}: var(${token})`);
2025
+ } else if (token.match(/--ds-border-radius-(sm|md|lg|xl)/)) {
2026
+ tailwind.push(`--radius-${token.replace("--ds-border-radius-", "")}: var(${token})`);
2027
+ } else if (token.match(/--ds-body-(sm|mg|lg)-body-font-size/)) {
2028
+ tailwind.push(`--text-${token.replace("--ds-body-", "").replace("-font-size", "")}: var(${token})`);
2029
+ } else if (token.match(/^--ds-size-\d+$/)) {
2030
+ tailwind.push(`--spacing-${token.replace("--ds-size-", "")}: var(${token})`);
2031
+ }
2032
+ }
2033
+ const dynamicColors = `[data-color] {
2034
+ --color-background-default: var(--ds-color-background-default);
2035
+ --color-background-tinted: var(--ds-color-background-tinted);
2036
+ --color-surface-default: var(--ds-color-surface-default);
2037
+ --color-surface-tinted: var(--ds-color-surface-tinted);
2038
+ --color-surface-hover: var(--ds-color-surface-hover);
2039
+ --color-surface-active: var(--ds-color-surface-active);
2040
+ --color-border-subtle: var(--ds-color-border-subtle);
2041
+ --color-border-default: var(--ds-color-border-default);
2042
+ --color-border-strong: var(--ds-color-border-strong);
2043
+ --color-text-subtle: var(--ds-color-text-subtle);
2044
+ --color-text-default: var(--ds-color-text-default);
2045
+ --color-base-default: var(--ds-color-base-default);
2046
+ --color-base-hover: var(--ds-color-base-hover);
2047
+ --color-base-active: var(--ds-color-base-active);
2048
+ --color-base-contrast-subtle: var(--ds-color-base-contrast-subtle);
2049
+ --color-base-contrast-default: var(--ds-color-base-contrast-default);
2050
+ }`;
2051
+ return `@theme {${tailwind.map((str) => `
2052
+ ${str};`).join("")}
2053
+ }
2054
+ ${dynamicColors}`;
2055
+ };
2056
+
2057
+ // src/tokens/process/output/theme.ts
2058
+ import chalk6 from "chalk";
2059
+ import * as R17 from "ramda";
2060
+
2061
+ // package.json
2062
+ var package_default = {
2063
+ name: "@digdir/designsystemet",
2064
+ version: "1.1.1",
2065
+ description: "CLI for Designsystemet",
2066
+ author: "Designsystemet team",
2067
+ engines: {
2068
+ node: ">=22.16.0"
2069
+ },
2070
+ repository: {
2071
+ type: "git",
2072
+ url: "git+https://github.com/digdir/designsystemet.git"
2073
+ },
2074
+ homepage: "https://github.com/digdir/designsystemet/tree/main/packages/cli",
2075
+ license: "MIT",
2076
+ type: "module",
2077
+ main: "./dist/src/index.js",
2078
+ files: [
2079
+ "./dist/**",
2080
+ "./configs/**"
2081
+ ],
2082
+ bin: "dist/bin/designsystemet.js",
2083
+ exports: {
2084
+ ".": {
2085
+ import: "./dist/src/index.js"
2086
+ },
2087
+ "./color": {
2088
+ import: "./dist/src/colors/index.js"
2089
+ },
2090
+ "./tokens": {
2091
+ import: "./dist/src/tokens/index.js"
2092
+ }
2093
+ },
2094
+ publishConfig: {
2095
+ access: "public"
2096
+ },
2097
+ scripts: {
2098
+ designsystemet: "tsx ./bin/designsystemet.ts",
2099
+ "designsystemet:inspect": "tsx --inspect-brk ./bin/designsystemet.ts",
2100
+ build: "tsup && pnpm build:types && pnpm build:json-schema",
2101
+ "build:types": "tsc --emitDeclarationOnly --declaration",
2102
+ "build:json-schema": "tsx ./src/scripts/createJsonSchema.ts",
2103
+ types: "tsc --noEmit",
2104
+ "test:tokens-create-options": 'pnpm run designsystemet tokens create -m dominant:"#007682" -n "#003333" -b 99 -o ./temp/options/design-tokens --theme options --clean',
2105
+ "test:tokens-create-config": "pnpm run designsystemet tokens create --config ./configs/test-tokens.config.json",
2106
+ "test:tokens-build": "pnpm run designsystemet tokens build -t ./temp/options/design-tokens -o ./temp/options/build --clean",
2107
+ "test:tokens-build-tailwind": "pnpm run designsystemet tokens build -t ./temp/options/design-tokens -o ./temp/options/build --clean --experimental-tailwind",
2108
+ "test:tokens-build-config": "pnpm run designsystemet tokens build -t ./temp/config/design-tokens -o ./temp/config/build --clean",
2109
+ "test:tokens-build-config:inspect": "pnpm run designsystemet:inspect tokens build -t ./temp/config/design-tokens -o ./temp/config/build --clean",
2110
+ "test:tokens-build-config-tailwind": "pnpm run designsystemet tokens build -t ./temp/config/design-tokens -o ./temp/config/build --clean --experimental-tailwind",
2111
+ "test:tokens-create-and-build-options": "pnpm test:tokens-create-options && pnpm test:tokens-build",
2112
+ "test:tokens-create-and-build-config": "pnpm test:tokens-create-config && pnpm test:tokens-build-config",
2113
+ test: "pnpm test:tokens-create-and-build-options && pnpm test:tokens-create-and-build-config",
2114
+ "digdir:tokens-build": "pnpm run designsystemet tokens build -t ../../internal/design-tokens -o ../../packages/theme/brand --clean --experimental-tailwind",
2115
+ "digdir:tokens-create": "pnpm run designsystemet tokens create --config ./configs/digdir.config.json",
2116
+ "update:template": "tsx ./src/scripts/update-template.ts",
2117
+ "update:theme-digdir": "pnpm digdir:tokens-create && tsx ./src/scripts/update-design-tokens.ts && pnpm digdir:tokens-build",
2118
+ verify: "pnpm test && pnpm update:template && pnpm update:theme-digdir && pnpm build:tokens"
2119
+ },
2120
+ dependencies: {
2121
+ "@commander-js/extra-typings": "^14.0.0",
2122
+ "@tokens-studio/sd-transforms": "1.3.0",
2123
+ "apca-w3": "^0.1.9",
2124
+ chalk: "^5.4.1",
2125
+ "change-case": "^5.4.4",
2126
+ "chroma-js": "^3.1.2",
2127
+ "colorjs.io": "^0.6.0-alpha.1",
2128
+ commander: "^14.0.0",
2129
+ "fast-glob": "^3.3.3",
2130
+ hsluv: "^1.0.1",
2131
+ "object-hash": "^3.0.0",
2132
+ postcss: "^8.5.6",
2133
+ ramda: "^0.30.1",
2134
+ "style-dictionary": "^5.0.0",
2135
+ zod: "^3.25.67",
2136
+ "zod-validation-error": "^3.5.2"
2137
+ },
2138
+ devDependencies: {
2139
+ "@tokens-studio/types": "0.5.2",
2140
+ "@types/apca-w3": "^0.1.3",
2141
+ "@types/chroma-js": "^3.1.1",
2142
+ "@types/fs-extra": "^11.0.4",
2143
+ "@types/glob": "^8.1.0",
2144
+ "@types/node": "^22.15.32",
2145
+ "@types/object-hash": "^3.0.6",
2146
+ "@types/ramda": "^0.30.2",
2147
+ "fs-extra": "^11.3.0",
2148
+ tslib: "^2.8.1",
2149
+ tsup: "^8.5.0",
2150
+ tsx: "^4.20.3",
2151
+ typescript: "^5.8.3"
2152
+ }
2153
+ };
2154
+
2155
+ // src/tokens/process/output/theme.ts
2156
+ var defaultFileHeader = `build: v${package_default.version}`;
2157
+ var createThemeCSSFiles = ({
2158
+ processedBuilds,
2159
+ fileHeader: fileHeader2 = defaultFileHeader
2160
+ }) => {
2161
+ const groupedByTheme = {};
2162
+ for (const [_, buildResults] of Object.entries(processedBuilds)) {
2163
+ for (const buildResult of buildResults) {
2164
+ const themeName = buildResult.permutation.theme;
2165
+ const newOutputs = buildResult.formatted;
2166
+ if (R17.isNotEmpty(newOutputs)) {
2167
+ const currentOutputs = groupedByTheme[themeName] ?? [];
2168
+ groupedByTheme[themeName] = R17.concat(currentOutputs, newOutputs);
2169
+ }
2170
+ }
2171
+ }
2172
+ const sortOrder = [
2173
+ "color-scheme/light",
2174
+ "typography/secondary",
2175
+ "semantic",
2176
+ "color-scheme/dark",
2177
+ "color-scheme/contrast",
2178
+ "typography/primary",
2179
+ "color/"
2180
+ ];
2181
+ const sortByDefinedOrder = R17.sortBy((file) => {
2182
+ const filePath = file.destination || "";
2183
+ const sortIndex = sortOrder.findIndex((sortElement) => {
2184
+ if (sortElement.endsWith("/")) {
2185
+ return filePath.includes(sortElement);
2186
+ }
2187
+ return filePath.includes(`${sortElement}.css`);
2188
+ });
2189
+ if (sortIndex === -1) {
2190
+ console.error(
2191
+ chalk6.yellow("WARNING: CSS section does not have a defined sort order:", filePath.replace(".css", ""))
2192
+ );
2193
+ console.log(
2194
+ chalk6.dim(
2195
+ `
2196
+ The section will currently be added to the end of the entry file, but the exact
2197
+ order may change due to nondeterminism.`.trim()
2198
+ )
2199
+ );
2200
+ return Infinity;
2201
+ }
2202
+ return sortIndex;
2203
+ });
2204
+ const header = `@charset "UTF-8";
2205
+ /*
2206
+ ${fileHeader2}
2207
+ */
2208
+
2209
+ `;
2210
+ const sortAlphabetically = R17.sort(R17.ascend((x) => x.destination || ""));
2211
+ const pickOutputs = R17.map(R17.view(R17.lensProp("output")));
2212
+ const themeCSSFile = R17.pipe(
2213
+ sortAlphabetically,
2214
+ sortByDefinedOrder,
2215
+ pickOutputs,
2216
+ R17.join("\n"),
2217
+ (content) => header + content
2218
+ );
2219
+ const themeCSSFiles = Object.entries(groupedByTheme).map(([theme, files]) => ({
2220
+ destination: `${theme}.css`,
2221
+ output: themeCSSFile(files)
2222
+ }));
2223
+ return themeCSSFiles;
2224
+ };
2225
+
2209
2226
  // src/tokens/build.ts
2210
2227
  async function write(files, outDir, dry) {
2211
2228
  for (const { destination, output } of files) {
@@ -2222,6 +2239,7 @@ var buildTokens = async (options) => {
2222
2239
  const outDir = path.resolve(options.outDir);
2223
2240
  const tokensDir = path.resolve(options.tokensDir);
2224
2241
  const $themes = JSON.parse(await readFile(`${tokensDir}/$themes.json`));
2242
+ const processed$themes = $themes.map(processThemeObject);
2225
2243
  let $designsystemet;
2226
2244
  try {
2227
2245
  const $designsystemetContent = await readFile(`${tokensDir}/$designsystemet.json`);
@@ -2229,30 +2247,30 @@ var buildTokens = async (options) => {
2229
2247
  } catch (_error) {
2230
2248
  }
2231
2249
  console.log(`
2232
- \u{1F3D7}\uFE0F Start building tokens in ${chalk6.green(tokensDir)}`);
2250
+ \u{1F3D7}\uFE0F Start building tokens in ${chalk7.green(tokensDir)}`);
2233
2251
  const processedBuilds = await processPlatform({
2234
2252
  ...options,
2235
2253
  outDir,
2236
2254
  tokensDir,
2237
2255
  type: "build",
2238
- $themes
2256
+ processed$themes
2239
2257
  });
2240
2258
  const fileHeader2 = R18.join("")([
2241
2259
  defaultFileHeader,
2242
2260
  $designsystemet ? `
2243
2261
  design-tokens: v${$designsystemet.version}` : ""
2244
2262
  ]);
2245
- let cssFiles = createThemeCSSFiles({ processedBuilds, fileHeader: fileHeader2 });
2263
+ let files = [];
2264
+ const declarationFiles = createTypeDeclarationFiles(processed$themes);
2265
+ const cssFiles = createThemeCSSFiles({ processedBuilds, fileHeader: fileHeader2 });
2266
+ files = [...declarationFiles, ...cssFiles];
2246
2267
  if (options.tailwind) {
2247
2268
  const tailwindFiles = createTailwindCSSFiles(cssFiles);
2248
- cssFiles = cssFiles.concat(tailwindFiles.filter(Boolean));
2269
+ files = files.concat(tailwindFiles.filter(Boolean));
2249
2270
  }
2250
2271
  console.log(`
2251
- \u{1F4BE} Writing build to ${chalk6.green(outDir)}`);
2252
- for (const { formatted } of processedBuilds.types) {
2253
- await write(formatted, outDir, options.dry);
2254
- }
2255
- await write(cssFiles, outDir, options.dry);
2272
+ \u{1F4BE} Writing build to ${chalk7.green(outDir)}`);
2273
+ await write(files, outDir, options.dry);
2256
2274
  console.log(`
2257
2275
  \u2705 Finished building tokens!`);
2258
2276
  return processedBuilds;
@@ -2260,7 +2278,7 @@ design-tokens: v${$designsystemet.version}` : ""
2260
2278
 
2261
2279
  // src/tokens/create/write.ts
2262
2280
  import path2 from "path";
2263
- import chalk7 from "chalk";
2281
+ import chalk8 from "chalk";
2264
2282
  import * as R19 from "ramda";
2265
2283
 
2266
2284
  // src/tokens/create/generators/$designsystemet.ts
@@ -2497,7 +2515,7 @@ var writeTokens = async (options) => {
2497
2515
  );
2498
2516
  const themes = concatThemeNames(themeObjects);
2499
2517
  console.log(`
2500
- Themes: ${chalk7.blue(themes.join(", "))}`);
2518
+ Themes: ${chalk8.blue(themes.join(", "))}`);
2501
2519
  const $themes = await generate$Themes(["dark", "light"], themes, colors2);
2502
2520
  const $metadata = generate$Metadata(["dark", "light"], themes, colors2);
2503
2521
  const $designsystemet = generate$Designsystemet();
@@ -2511,7 +2529,7 @@ Themes: ${chalk7.blue(themes.join(", "))}`);
2511
2529
  await writeFile(filePath, stringify(tokens), dry);
2512
2530
  }
2513
2531
  console.log(
2514
- `Finished creating Designsystem design tokens in ${chalk7.green(outDir)} for theme ${chalk7.blue(themeName)}`
2532
+ `Finished creating Designsystem design tokens in ${chalk8.green(outDir)} for theme ${chalk8.blue(themeName)}`
2515
2533
  );
2516
2534
  };
2517
2535
 
@@ -4274,14 +4292,14 @@ var createTokens = async (opts) => {
4274
4292
 
4275
4293
  // bin/config.ts
4276
4294
  import path4 from "path";
4277
- import chalk9 from "chalk";
4295
+ import chalk10 from "chalk";
4278
4296
  import * as R25 from "ramda";
4279
4297
 
4280
4298
  // src/config.ts
4281
- import chalk8 from "chalk";
4299
+ import chalk9 from "chalk";
4282
4300
  import * as R24 from "ramda";
4283
4301
  import { z } from "zod/v4";
4284
- import { fromError } from "zod-validation-error";
4302
+ import { fromError } from "zod-validation-error/v4";
4285
4303
  function mapPathToOptionName(path5) {
4286
4304
  const normalisedPath = path5[0] === "themes" ? ["theme", ...R24.drop(2, path5)] : path5;
4287
4305
  const option = R24.path(normalisedPath, cliOptions);
@@ -4291,38 +4309,42 @@ function mapPathToOptionName(path5) {
4291
4309
  return option;
4292
4310
  }
4293
4311
  function makeFriendlyError(err) {
4294
- return fromError(err, {
4295
- messageBuilder: (issues) => issues.map((issue) => {
4296
- const issuePath = issue.path.join(".");
4297
- const optionName = mapPathToOptionName(issue.path);
4298
- const errorCode = `(error code: ${issue.code})`;
4299
- const optionMessage = optionName ? ` or CLI option --${optionName}` : "";
4300
- return ` - Error in JSON value ${chalk8.red(issuePath)}${optionMessage}:
4301
- ${issue.message} ${chalk8.dim(errorCode)}`;
4302
- }).join("\n")
4303
- });
4312
+ try {
4313
+ return fromError(err, {
4314
+ messageBuilder: (issues) => issues.map((issue) => {
4315
+ const issuePath = issue.path.join(".");
4316
+ const optionName = mapPathToOptionName(issue.path);
4317
+ const errorCode = `(error code: ${issue.code})`;
4318
+ const optionMessage = optionName ? ` or CLI option --${optionName}` : "";
4319
+ return ` - Error in JSON value ${chalk9.red(issuePath)}${optionMessage}:
4320
+ ${issue.message} ${chalk9.dim(errorCode)}`;
4321
+ }).join("\n")
4322
+ });
4323
+ } catch (_err2) {
4324
+ console.error(chalk9.red(err instanceof Error ? err.message : "Unknown error occurred while parsing config file"));
4325
+ console.error(err instanceof Error ? err.stack : "No stack trace available");
4326
+ }
4304
4327
  }
4305
4328
  function validateConfig(schema, unvalidatedConfig, configPath) {
4306
4329
  try {
4307
4330
  return schema.parse(unvalidatedConfig);
4308
4331
  } catch (err) {
4309
- console.error(chalk8.redBright(`Invalid config file at ${chalk8.red(configPath)}`));
4332
+ console.error(chalk9.redBright(`Invalid config file at ${chalk9.red(configPath)}`));
4310
4333
  const validationError = makeFriendlyError(err);
4311
- console.error(validationError.toString());
4334
+ console.error(validationError?.toString());
4312
4335
  process.exit(1);
4313
4336
  }
4314
4337
  }
4315
- function parseConfig(schema, configFile, configPath) {
4338
+ function parseConfig(configFile, configPath) {
4316
4339
  if (!configFile) {
4317
4340
  return {};
4318
4341
  }
4319
4342
  try {
4320
- const parsedConfig = JSON.parse(configFile);
4321
- return schema.parse(parsedConfig);
4343
+ return JSON.parse(configFile);
4322
4344
  } catch (err) {
4323
- console.error(chalk8.redBright(`Failed parsing config file at ${chalk8.red(configPath)}`));
4345
+ console.error(chalk9.redBright(`Failed parsing config file at ${chalk9.red(configPath)}`));
4324
4346
  const validationError = makeFriendlyError(err);
4325
- console.error(validationError.toString());
4347
+ console.error(validationError?.toString());
4326
4348
  process.exit(1);
4327
4349
  }
4328
4350
  }
@@ -4360,17 +4382,16 @@ var themeSchema = z.object({
4360
4382
  }).describe("Defines the typography for a given theme").optional(),
4361
4383
  borderRadius: z.number().meta({ description: "Defines the border-radius for this theme" }).optional()
4362
4384
  }).meta({ description: "An object defining a theme. The property name holding the object becomes the theme name." });
4363
- var configFileBuildSchema = z.object({
4385
+ var commonConfig = z.object({
4364
4386
  clean: z.boolean().meta({ description: "Delete the output directory before building or creating tokens" }).optional()
4365
4387
  });
4366
- var configFileCreateSchema = z.object({
4388
+ var _configFileCreateSchema = z.object({
4367
4389
  outDir: z.string().meta({ description: "Path to the output directory for the created design tokens" }),
4368
- clean: z.boolean().meta({ description: "Delete the output directory before building or creating tokens" }).optional(),
4369
4390
  themes: z.record(z.string(), themeSchema).meta({
4370
4391
  description: "An object with one or more themes. Each property defines a theme, and the property name is used as the theme name."
4371
4392
  })
4372
4393
  }).required();
4373
- var combinedConfigSchema = configFileCreateSchema.extend(configFileBuildSchema.shape);
4394
+ var configFileCreateSchema = _configFileCreateSchema.extend(commonConfig.shape);
4374
4395
 
4375
4396
  // bin/options.ts
4376
4397
  var getOptionIfMatchingSource = (...sources) => (command, option) => {
@@ -4393,26 +4414,22 @@ async function readConfigFile(configPath, allowFileNotFound = true) {
4393
4414
  if (allowFileNotFound) {
4394
4415
  return "";
4395
4416
  }
4396
- console.error(chalk9.redBright(`Could not read config file at ${chalk9.blue(resolvedPath)}`));
4417
+ console.error(chalk10.redBright(`Could not read config file at ${chalk10.blue(resolvedPath)}`));
4397
4418
  throw err;
4398
4419
  }
4399
4420
  if (configFile) {
4400
- console.log(`Found config file: ${chalk9.green(resolvedPath)}`);
4421
+ console.log(`Found config file: ${chalk10.green(resolvedPath)}`);
4401
4422
  }
4402
4423
  return configFile;
4403
4424
  }
4404
4425
  async function parseCreateConfig(configFile, options) {
4405
4426
  const { cmd, theme = "theme", configPath } = options;
4406
- const configParsed = parseConfig(
4407
- configFileCreateSchema,
4408
- configFile,
4409
- configPath
4410
- );
4427
+ const configParsed = parseConfig(configFile, configPath);
4411
4428
  const themeColors = Object.values(configParsed?.themes ?? {}).map(
4412
4429
  (x) => /* @__PURE__ */ new Set([...R25.keys(x.colors.main), ...R25.keys(x.colors.support)])
4413
4430
  );
4414
4431
  if (!R25.all(R25.equals(R25.__, themeColors[0]), themeColors)) {
4415
- console.error(chalk9.redBright(`In config, all themes must have the same custom color names, but we found:`));
4432
+ console.error(chalk10.redBright(`In config, all themes must have the same custom color names, but we found:`));
4416
4433
  const themeNames = R25.keys(configParsed.themes ?? {});
4417
4434
  themeColors.forEach((colors2, index) => {
4418
4435
  const colorNames = Array.from(colors2);
@@ -4453,8 +4470,8 @@ async function parseCreateConfig(configFile, options) {
4453
4470
  return validateConfig(configFileCreateSchema, unvalidatedConfig, configPath);
4454
4471
  }
4455
4472
  async function parseBuildConfig(configFile, { configPath }) {
4456
- const configParsed = parseConfig(configFileBuildSchema, configFile, configPath);
4457
- return validateConfig(configFileBuildSchema, configParsed, configPath);
4473
+ const configParsed = parseConfig(configFile, configPath);
4474
+ return validateConfig(commonConfig, configParsed, configPath);
4458
4475
  }
4459
4476
 
4460
4477
  // bin/designsystemet.ts
@@ -4466,11 +4483,11 @@ var DEFAULT_THEME_NAME = "theme";
4466
4483
  var DEFAULT_CONFIG_FILE = "designsystemet.config.json";
4467
4484
  function makeTokenCommands() {
4468
4485
  const tokenCmd = createCommand("tokens");
4469
- tokenCmd.command("build").description("Build Designsystemet tokens").option("-t, --tokens <string>", `Path to ${chalk10.blue("design-tokens")}`, DEFAULT_TOKENS_CREATE_DIR).option(
4486
+ tokenCmd.command("build").description("Build Designsystemet tokens").option("-t, --tokens <string>", `Path to ${chalk11.blue("design-tokens")}`, DEFAULT_TOKENS_CREATE_DIR).option(
4470
4487
  "-o, --out-dir <string>",
4471
- `Output directory for built ${chalk10.blue("design-tokens")}`,
4488
+ `Output directory for built ${chalk11.blue("design-tokens")}`,
4472
4489
  DEFAULT_TOKENS_BUILD_DIR
4473
- ).option(`--${cliOptions.clean} [boolean]`, "Clean output directory before building tokens", parseBoolean, false).option("--dry [boolean]", `Dry run for built ${chalk10.blue("design-tokens")}`, parseBoolean, false).option("-p, --preview", "Generate preview token.ts files", false).option("--verbose", "Enable verbose output", false).option("--config <string>", `Path to config file (default: "${DEFAULT_CONFIG_FILE}")`).option("--experimental-tailwind", "Generate Tailwind CSS classes for tokens", false).action(async (opts) => {
4490
+ ).option(`--${cliOptions.clean} [boolean]`, "Clean output directory before building tokens", parseBoolean, false).option("--dry [boolean]", `Dry run for built ${chalk11.blue("design-tokens")}`, parseBoolean, false).option("-p, --preview", "Generate preview token.ts files", false).option("--verbose", "Enable verbose output", false).option("--config <string>", `Path to config file (default: "${DEFAULT_CONFIG_FILE}")`).option("--experimental-tailwind", "Generate Tailwind CSS classes for tokens", false).action(async (opts) => {
4474
4491
  const { preview, verbose, clean, dry, experimentalTailwind } = opts;
4475
4492
  const tokensDir = typeof opts.tokens === "string" ? opts.tokens : DEFAULT_TOKENS_CREATE_DIR;
4476
4493
  const outDir = typeof opts.outDir === "string" ? opts.outDir : "./dist/tokens";
@@ -4487,9 +4504,9 @@ function makeTokenCommands() {
4487
4504
  });
4488
4505
  tokenCmd.command("create").description("Create Designsystemet tokens").option(`-m, --${cliOptions.theme.colors.main} <name:hex...>`, `Main colors`, parseColorValues).option(`-s, --${cliOptions.theme.colors.support} <name:hex...>`, `Support colors`, parseColorValues).option(`-n, --${cliOptions.theme.colors.neutral} <hex>`, `Neutral hex color`, convertToHex).option(
4489
4506
  `-o, --${cliOptions.outDir} <string>`,
4490
- `Output directory for created ${chalk10.blue("design-tokens")}`,
4507
+ `Output directory for created ${chalk11.blue("design-tokens")}`,
4491
4508
  DEFAULT_TOKENS_CREATE_DIR
4492
- ).option(`--${cliOptions.clean} [boolean]`, "Clean output directory before creating tokens", parseBoolean, false).option("--dry [boolean]", `Dry run for created ${chalk10.blue("design-tokens")}`, parseBoolean, false).option(`-f, --${cliOptions.theme.typography.fontFamily} <string>`, `Font family (experimental)`, DEFAULT_FONT).option(
4509
+ ).option(`--${cliOptions.clean} [boolean]`, "Clean output directory before creating tokens", parseBoolean, false).option("--dry [boolean]", `Dry run for created ${chalk11.blue("design-tokens")}`, parseBoolean, false).option(`-f, --${cliOptions.theme.typography.fontFamily} <string>`, `Font family (experimental)`, DEFAULT_FONT).option(
4493
4510
  `-b, --${cliOptions.theme.borderRadius} <number>`,
4494
4511
  `Unitless base border-radius in px`,
4495
4512
  (radiusAsString) => Number(radiusAsString),
@@ -4530,8 +4547,8 @@ program.command("migrate").description("run a Designsystemet migration").addArgu
4530
4547
  console.error("Migration not found!");
4531
4548
  throw "Aborting";
4532
4549
  }
4533
- console.log(`Applying migration ${chalk10.blue(migrationKey)} with glob: ${chalk10.green(glob2)}`);
4534
- migration?.(glob2).then(() => console.log(`Migration ${chalk10.blue(migrationKey)} finished`)).catch((error) => console.log(error));
4550
+ console.log(`Applying migration ${chalk11.blue(migrationKey)} with glob: ${chalk11.green(glob2)}`);
4551
+ migration?.(glob2).then(() => console.log(`Migration ${chalk11.blue(migrationKey)} finished`)).catch((error) => console.log(error));
4535
4552
  } else {
4536
4553
  console.log("Migrate: please specify a migration name or --list");
4537
4554
  }