unholy-design-tokens 1.0.0
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.
- package/.github/workflows/lint-format-build.yml +35 -0
- package/.github/workflows/publish_release.yml +18 -0
- package/.prettierrc +9 -0
- package/ANALOGY_HOUSE.md +139 -0
- package/ANALOGY_I18NEXT.md +160 -0
- package/LICENSE +201 -0
- package/README.md +90 -0
- package/WHY_THIS_EXISTS.md +74 -0
- package/bin/build-tokens.ts +34 -0
- package/build/css/bg/bg.css +60 -0
- package/build/css/border/border.css +51 -0
- package/build/css/colors.css +204 -0
- package/build/css/conditional.css +8 -0
- package/build/css/cube/cube.block.css +18 -0
- package/build/css/cube/cube.composition.css +16 -0
- package/build/css/cube/cube.utility.css +185 -0
- package/build/css/font/font.css +24 -0
- package/build/css/space.css +20 -0
- package/build/css/text/text.css +48 -0
- package/build/css/themes/private-theme.css +228 -0
- package/build/css/themes/public-theme.css +228 -0
- package/build/css/variant/variant.css +42 -0
- package/build/css/variants.css +167 -0
- package/build/types/theme.d.ts +932 -0
- package/build/types/tokens.ts +653 -0
- package/dist/bin/build-tokens.js +27 -0
- package/dist/scripts/build-style-dictionary.js +32 -0
- package/dist/scripts/generate-typography-tokens.js +125 -0
- package/dist/src/colors/color.config.js +45 -0
- package/dist/src/colors/color.filter.js +19 -0
- package/dist/src/colors/color.formatter.js +25 -0
- package/dist/src/colors/index.js +2 -0
- package/dist/src/cube-css/cube.config.js +42 -0
- package/dist/src/cube-css/cube.formatter.js +89 -0
- package/dist/src/style-dictionary.config.js +143 -0
- package/dist/src/type-declarations/type-declarations.config.js +29 -0
- package/dist/src/type-declarations/type-declarations.formatter.js +111 -0
- package/dist/src/utils/helpers.js +9 -0
- package/dist/src/utils/index.js +4 -0
- package/dist/src/utils/template.js +83 -0
- package/dist/src/utils/tokens.js +80 -0
- package/dist/src/utils/utopia.js +19 -0
- package/eslint.config.js +67 -0
- package/package.json +60 -0
- package/scripts/build-style-dictionary.ts +44 -0
- package/scripts/generate-typography-tokens.ts +138 -0
- package/src/LICENSE +201 -0
- package/src/README.md +88 -0
- package/src/colors/color.config.ts +48 -0
- package/src/colors/color.filter.ts +28 -0
- package/src/colors/color.formatter.ts +43 -0
- package/src/colors/index.ts +6 -0
- package/src/cube-css/cube.config.ts +50 -0
- package/src/cube-css/cube.formatter.ts +104 -0
- package/src/formatters/spacing.js +95 -0
- package/src/style-dictionary.config.ts +151 -0
- package/src/theme/README.md +256 -0
- package/src/theme/cube-theme-addon.js +44 -0
- package/src/theme/helper.js +38 -0
- package/src/theme/index.js +6 -0
- package/src/theme/theme.config.js +42 -0
- package/src/theme/theme.filter.js +42 -0
- package/src/theme/theme.formatter.js +71 -0
- package/src/tokens/1 - primitives/README.md +58 -0
- package/src/tokens/1 - primitives/border.json +54 -0
- package/src/tokens/1 - primitives/breakpoint.json +10 -0
- package/src/tokens/1 - primitives/color-pool.json +266 -0
- package/src/tokens/1 - primitives/color.json +266 -0
- package/src/tokens/1 - primitives/font-scale.json +27 -0
- package/src/tokens/1 - primitives/font.json +23 -0
- package/src/tokens/1 - primitives/shadow.json +26 -0
- package/src/tokens/1 - primitives/space.json +27 -0
- package/src/tokens/2 - semantic/README.md +49 -0
- package/src/tokens/2 - semantic/border.json +27 -0
- package/src/tokens/2 - semantic/color.json +263 -0
- package/src/tokens/2 - semantic/details.md +1 -0
- package/src/tokens/2 - semantic/layout.json +52 -0
- package/src/tokens/2 - semantic/radius.json +13 -0
- package/src/tokens/2 - semantic/shadow.json +19 -0
- package/src/tokens/2 - semantic/spacing.json +25 -0
- package/src/tokens/3 - intent/README.md +43 -0
- package/src/tokens/3 - intent/background.json +135 -0
- package/src/tokens/3 - intent/color.json +265 -0
- package/src/tokens/3 - intent/font.json +61 -0
- package/src/tokens/3 - intent/text +67 -0
- package/src/tokens/README.md +176 -0
- package/src/tokens/color/brand.json +316 -0
- package/src/tokens/component/theming.json +69 -0
- package/src/tokens/conditional.json +40 -0
- package/src/tokens/custom/4 - (OPTIONAL) cube css/README.md +38 -0
- package/src/tokens/custom/4 - (OPTIONAL) cube css/block.json +24 -0
- package/src/tokens/custom/4 - (OPTIONAL) cube css/composition.json +26 -0
- package/src/tokens/custom/4 - (OPTIONAL) cube css/global.json +15 -0
- package/src/tokens/custom/4 - (OPTIONAL) cube css/utility.json +224 -0
- package/src/tokens/custom/OKlch/color.json +61 -0
- package/src/tokens/custom/OKlch/state.json +107 -0
- package/src/tokens/custom/OKlch/theme-color.json +34 -0
- package/src/tokens/custom/OKlch/variant.json +67 -0
- package/src/tokens/custom/components/highlighted.json +16 -0
- package/src/tokens/state.js +29 -0
- package/src/tokens/theme-color.json +34 -0
- package/src/type-declarations/type-declarations.config.ts +34 -0
- package/src/type-declarations/type-declarations.formatter.ts +122 -0
- package/src/utils/helpers.ts +11 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/template.ts +110 -0
- package/src/utils/tokens.ts +95 -0
- package/src/utils/utopia.ts +36 -0
- package/tailwind.md +720 -0
- package/tsconfig.json +19 -0
- package/turbowatch.ts +14 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for template generation.
|
|
3
|
+
* https://styledictionary.com/reference/hooks/formats/#using-a-template--templating-engine-to-create-a-format
|
|
4
|
+
*/
|
|
5
|
+
import { capitalizeFirstLetter } from "./helpers.js";
|
|
6
|
+
export { generateHeader, generateSubheader, formatInLayer, generateFigmaHeaderReference, };
|
|
7
|
+
const startComment = "/* ";
|
|
8
|
+
const endComment = " */";
|
|
9
|
+
const headerLength = 60;
|
|
10
|
+
const subheaderLength = 20;
|
|
11
|
+
const separatorChar = "-";
|
|
12
|
+
const headerSeparator = " ";
|
|
13
|
+
function generateSeparator(length) {
|
|
14
|
+
return `${startComment}${separatorChar.repeat(length)}${endComment}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Will generate a comment block like this:
|
|
18
|
+
/* ------------------------------------------------------------ *\/
|
|
19
|
+
/* Title *\/
|
|
20
|
+
/* ------------------------------------------------------------ *\/
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
function generateCommentBlock(title, totalLength, separatorChar, indent = "") {
|
|
24
|
+
let titleTotalLength = totalLength - title.length;
|
|
25
|
+
let halfLength = Math.floor(titleTotalLength / 2);
|
|
26
|
+
let titleSeparator = headerSeparator.repeat(halfLength);
|
|
27
|
+
if (totalLength % 2 !== 0) {
|
|
28
|
+
titleSeparator += separatorChar;
|
|
29
|
+
}
|
|
30
|
+
return (`\n${indent}${generateSeparator(totalLength)}` +
|
|
31
|
+
`\n${indent}${startComment}${titleSeparator}${title}${titleSeparator}${endComment}` +
|
|
32
|
+
`\n${indent}${generateSeparator(totalLength)}\n`);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generates a header comment block for a given header string.
|
|
36
|
+
* /* ------------------------------------------------------------ *\/
|
|
37
|
+
* /* Header *\/
|
|
38
|
+
* /* ------------------------------------------------------------ *\/
|
|
39
|
+
*/
|
|
40
|
+
function generateHeader(header) {
|
|
41
|
+
if (!header)
|
|
42
|
+
return "";
|
|
43
|
+
return generateCommentBlock(capitalizeFirstLetter(header), headerLength, separatorChar, "");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Generates a subheader comment block for a given subheader string.
|
|
47
|
+
* /* ---------------------- \/*
|
|
48
|
+
* /* Subheader *\/
|
|
49
|
+
* /* ---------------------- *\/
|
|
50
|
+
*/
|
|
51
|
+
function generateSubheader(subheader) {
|
|
52
|
+
if (!subheader)
|
|
53
|
+
return "";
|
|
54
|
+
return generateCommentBlock(capitalizeFirstLetter(subheader), subheaderLength, separatorChar, " ");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Formats content within a CSS layer block.
|
|
58
|
+
* @layer name {
|
|
59
|
+
* :root {
|
|
60
|
+
* --variable: value;
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
*/
|
|
64
|
+
function formatInLayer(name, content) {
|
|
65
|
+
let result = `@layer ${name} {`;
|
|
66
|
+
result += `\n`;
|
|
67
|
+
result += ` :root {`;
|
|
68
|
+
result += `\n`;
|
|
69
|
+
result += `${content}`;
|
|
70
|
+
result += ` }\n`;
|
|
71
|
+
result += `}\n`;
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Generates a Figma header reference comment block
|
|
76
|
+
* /* Collection name: <collectionName> *\/
|
|
77
|
+
* /* Mode: <mode> *\/
|
|
78
|
+
*
|
|
79
|
+
* See https://www.figma.com/community/plugin/1470777269812001046/css-variables-import-export
|
|
80
|
+
*/
|
|
81
|
+
function generateFigmaHeaderReference(collectionName, mode = "Light") {
|
|
82
|
+
return `/* Collection name: ${collectionName} */\n/* Mode: ${mode} */`;
|
|
83
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { getReferences, usesReferences } from 'style-dictionary/utils';
|
|
2
|
+
import { toKebab } from './helpers.js';
|
|
3
|
+
export function tokenName(token) {
|
|
4
|
+
const attrs = token.attributes;
|
|
5
|
+
const path = attrs?.item ? [attrs.category, attrs.type, attrs.item] : token.path;
|
|
6
|
+
return path.join('-');
|
|
7
|
+
}
|
|
8
|
+
// TODO:
|
|
9
|
+
export function resolveTokenReferences(token, options, dictionary, privateVar = false) {
|
|
10
|
+
const originalValue = token.original?.value;
|
|
11
|
+
// if (!shouldOutputReferences(token, options, dictionary)) {
|
|
12
|
+
// return originalValue != null
|
|
13
|
+
// ? cssValue(originalValue)
|
|
14
|
+
// : cssValue(token.value);
|
|
15
|
+
// }
|
|
16
|
+
if (!originalValue)
|
|
17
|
+
return cssValue(token.value);
|
|
18
|
+
// if (
|
|
19
|
+
// (originalValueParsed && originalValueParsed.startsWith("var(--")) ||
|
|
20
|
+
// originalValueParsed.startsWith("calc") ||
|
|
21
|
+
// originalValueParsed.startsWith("clamp")
|
|
22
|
+
// ) {
|
|
23
|
+
// ("📟 - cssValue(originalValue) → ", cssValue(originalValue));
|
|
24
|
+
// return originalValue;
|
|
25
|
+
// }
|
|
26
|
+
if (!usesReferences(originalValue))
|
|
27
|
+
return cssValue(token.value);
|
|
28
|
+
if (!shouldOutputReferences(token, options, dictionary)) {
|
|
29
|
+
return rewriteOriginalRefs(originalValue, dictionary.tokens, privateVar);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return cssValue(originalValue);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function refToTokenRefString(ref) {
|
|
36
|
+
// Verify if the ref is a style-dictionary reference object pattern or a direct var(--...) string
|
|
37
|
+
const refPath = ref.ref ?? ref.path;
|
|
38
|
+
return `{${refPath.join('.')}}`;
|
|
39
|
+
}
|
|
40
|
+
export function refToCssVar(ref, privateVar) {
|
|
41
|
+
return `var(--${privateVar ? '_' : ''}${toKebab(ref.name)})`;
|
|
42
|
+
}
|
|
43
|
+
const cssValue = (v) => {
|
|
44
|
+
if (v == null)
|
|
45
|
+
return '';
|
|
46
|
+
if (typeof v === 'string')
|
|
47
|
+
return v;
|
|
48
|
+
if (typeof v === 'number')
|
|
49
|
+
return String(v);
|
|
50
|
+
if (typeof v === 'boolean')
|
|
51
|
+
return v ? 'true' : 'false';
|
|
52
|
+
if (Array.isArray(v))
|
|
53
|
+
return v.join(',');
|
|
54
|
+
return JSON.stringify(v);
|
|
55
|
+
};
|
|
56
|
+
export function rewriteOriginalRefs(originalValue, dictionaryTokens, privateVar) {
|
|
57
|
+
if (typeof originalValue !== 'string' || !usesReferences(originalValue))
|
|
58
|
+
return null;
|
|
59
|
+
const refs = getReferences(originalValue, dictionaryTokens);
|
|
60
|
+
let out = originalValue;
|
|
61
|
+
for (const ref of refs) {
|
|
62
|
+
out = out.replaceAll(refToTokenRefString(ref), refToCssVar(ref, privateVar));
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
export function shouldOutputReferences(token, options, dictionary) {
|
|
67
|
+
const originalValue = token.original?.value;
|
|
68
|
+
if (!usesReferences(originalValue))
|
|
69
|
+
return false;
|
|
70
|
+
const originalValueParsed = cssValue(originalValue);
|
|
71
|
+
if ((originalValueParsed && originalValueParsed.startsWith('var(--')) ||
|
|
72
|
+
originalValueParsed.startsWith('calc') ||
|
|
73
|
+
originalValueParsed.startsWith('clamp')) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const { usesDtcg, outputReferences } = options ?? {};
|
|
77
|
+
return typeof outputReferences === 'function'
|
|
78
|
+
? outputReferences(token, { dictionary, usesDtcg })
|
|
79
|
+
: Boolean(outputReferences);
|
|
80
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/utils/utopia.js
|
|
2
|
+
/**
|
|
3
|
+
* Generate a Utopia fluid type scale.
|
|
4
|
+
*
|
|
5
|
+
* Based on https://utopia.fyi/type/calculator/
|
|
6
|
+
* by James Gilyead & Trys Mudford
|
|
7
|
+
*/
|
|
8
|
+
export function generateUtopiaScale({ minViewport = 360, maxViewport = 1280, minFont = 16, maxFont = 20, scaleMin = 1.2, scaleMax = 1.25, steps = [-2, -1, 0, 1, 2, 3, 4], } = {}) {
|
|
9
|
+
const results = {};
|
|
10
|
+
steps.forEach((step) => {
|
|
11
|
+
const minSize = minFont * scaleMin ** step;
|
|
12
|
+
const maxSize = maxFont * scaleMax ** step;
|
|
13
|
+
const slope = ((maxSize - minSize) / (maxViewport - minViewport)) * 100;
|
|
14
|
+
const intercept = minSize - (slope / 100) * minViewport;
|
|
15
|
+
const clampValue = `clamp(${minSize / 16}rem, ${intercept / 16}rem + ${slope}vw, ${maxSize / 16}rem)`;
|
|
16
|
+
results[step] = clampValue;
|
|
17
|
+
});
|
|
18
|
+
return results;
|
|
19
|
+
}
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import css from '@eslint/css'
|
|
2
|
+
import js from '@eslint/js'
|
|
3
|
+
import json from '@eslint/json'
|
|
4
|
+
import markdown from '@eslint/markdown'
|
|
5
|
+
import { defineConfig } from 'eslint/config'
|
|
6
|
+
import globals from 'globals'
|
|
7
|
+
|
|
8
|
+
export default defineConfig([
|
|
9
|
+
{
|
|
10
|
+
ignores: [
|
|
11
|
+
'dist/**',
|
|
12
|
+
'build/**',
|
|
13
|
+
'node_modules/**',
|
|
14
|
+
'**/package-lock.json',
|
|
15
|
+
'**/yarn.lock',
|
|
16
|
+
'**/pnpm-lock.yaml',
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
files: ['**/*.{js,mjs,cjs, ts, mts}'],
|
|
21
|
+
plugins: { js },
|
|
22
|
+
extends: ['js/recommended'],
|
|
23
|
+
languageOptions: { globals: { ...globals.browser, ...globals.node } },
|
|
24
|
+
rules: {
|
|
25
|
+
'no-console': 'error',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
files: ['**/*.json'],
|
|
30
|
+
ignores: ['**/tokens/**/*.json'],
|
|
31
|
+
plugins: { json },
|
|
32
|
+
language: 'json/json',
|
|
33
|
+
extends: ['json/recommended'],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
files: ['**/tokens/**/*.json'],
|
|
37
|
+
plugins: { json },
|
|
38
|
+
language: 'json/json5',
|
|
39
|
+
extends: ['json/recommended'],
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
files: ['**/*.json5'],
|
|
43
|
+
plugins: { json },
|
|
44
|
+
language: 'json/json5',
|
|
45
|
+
extends: ['json/recommended'],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
files: ['**/*.md'],
|
|
49
|
+
plugins: { markdown },
|
|
50
|
+
language: 'markdown/commonmark',
|
|
51
|
+
extends: ['markdown/recommended'],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
files: ['**/*.css'],
|
|
55
|
+
plugins: { css },
|
|
56
|
+
language: 'css/css',
|
|
57
|
+
extends: ['css/recommended'],
|
|
58
|
+
rules: {
|
|
59
|
+
'css/no-invalid-properties': [
|
|
60
|
+
'error',
|
|
61
|
+
{
|
|
62
|
+
allowUnknownVariables: true,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
])
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "unholy-design-tokens",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/build-tokens.js",
|
|
6
|
+
"module": "dist/build-tokens.js",
|
|
7
|
+
"types": "dist/build-tokens.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"package.json": "./dist/package.json",
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/build-tokens.js",
|
|
12
|
+
"require": "./dist/build-tokens.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"scripts": {
|
|
17
|
+
"clean": "rm -rf build",
|
|
18
|
+
"tokens:typography": "node scripts/generate-typography-tokens.js",
|
|
19
|
+
"build:ts": "tsc",
|
|
20
|
+
"build": "pnpm run build:ts",
|
|
21
|
+
"prepack": "pnpm run build",
|
|
22
|
+
"build-tokens": "node scripts/generate-typography-tokens.js && pnpm run build:ts && node dist/build-tokens.js",
|
|
23
|
+
"build-tokens:verbose": "node scripts/generate-typography-tokens.js && pnpm run build:ts && node dist/build-tokens.js --verbose",
|
|
24
|
+
"build:verbose": "pnpm exec build-tokens -- --verbose",
|
|
25
|
+
"build-TODO:": "build-tokens -- --buildPath=./build/ --source=./src/tokens/ --destination=./build/ --test",
|
|
26
|
+
"lint": "eslint .",
|
|
27
|
+
"format": "prettier --write src/**/*.ts src/**/*.js",
|
|
28
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
29
|
+
},
|
|
30
|
+
"author": "",
|
|
31
|
+
"license": "Apache-2.0",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@eslint/css": "^0.14.1",
|
|
34
|
+
"@eslint/js": "^9.39.2",
|
|
35
|
+
"@eslint/json": "^0.14.0",
|
|
36
|
+
"@eslint/markdown": "^7.5.1",
|
|
37
|
+
"@types/node": "24.5.1",
|
|
38
|
+
"@types/tinycolor2": "1.4.6",
|
|
39
|
+
"eslint": "^9.39.2",
|
|
40
|
+
"eslint-config-prettier": "^10.1.8",
|
|
41
|
+
"globals": "^16.5.0",
|
|
42
|
+
"prettier": "3.7.4",
|
|
43
|
+
"style-dictionary": "^4.0.0-prerelease.30",
|
|
44
|
+
"tinycolor2": "1.6.0",
|
|
45
|
+
"prettier-plugin-organize-imports": "4.1.0",
|
|
46
|
+
"ts-node": "^10.9.2",
|
|
47
|
+
"tslib": "^2.8.1",
|
|
48
|
+
"tsx": "^4.21.0",
|
|
49
|
+
"typescript": "5.9.3",
|
|
50
|
+
"typescript-eslint": "^8.50.0"
|
|
51
|
+
},
|
|
52
|
+
"bin": {
|
|
53
|
+
"build-tokens": "./dist/bin/build-tokens.js"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"commander": "^14.0.2",
|
|
57
|
+
"install": "^0.13.0",
|
|
58
|
+
"turbowatch": "^2.29.4"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import StyleDictionary from 'style-dictionary'
|
|
3
|
+
import { logVerbosityLevels } from 'style-dictionary/enums'
|
|
4
|
+
import styleDictionaryConfig from '../src/style-dictionary.config'
|
|
5
|
+
import {
|
|
6
|
+
tokensDeclarationFormatter,
|
|
7
|
+
typesDeclarationFormatter,
|
|
8
|
+
} from '../src/type-declarations/type-declarations.formatter.js'
|
|
9
|
+
import { generateTypographyTokens } from './generate-typography-tokens'
|
|
10
|
+
|
|
11
|
+
function ensureTrailingSlash(p: string): string {
|
|
12
|
+
// Style Dictionary wants POSIX-ish trailing slash, even on Windows it accepts `/`
|
|
13
|
+
return p.endsWith(path.sep) ? p : p + path.sep
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function buildStyleDictionary(outDir: string) {
|
|
17
|
+
// 1️⃣ Generate typography tokens FIRST
|
|
18
|
+
generateTypographyTokens()
|
|
19
|
+
|
|
20
|
+
// clone config so we can override buildPath safely
|
|
21
|
+
const config = {
|
|
22
|
+
...styleDictionaryConfig,
|
|
23
|
+
platforms: Object.fromEntries(
|
|
24
|
+
Object.entries(styleDictionaryConfig.platforms).map(([name, platform]) => [
|
|
25
|
+
name,
|
|
26
|
+
{ ...platform },
|
|
27
|
+
]),
|
|
28
|
+
),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
for (const platform of Object.values(config.platforms)) {
|
|
32
|
+
platform.buildPath = ensureTrailingSlash(path.resolve(outDir, platform.buildPath ?? './build/'))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let sd = new StyleDictionary(config, {
|
|
36
|
+
verbosity: logVerbosityLevels.verbose,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
// Types formatters
|
|
40
|
+
StyleDictionary.registerFormat(typesDeclarationFormatter)
|
|
41
|
+
StyleDictionary.registerFormat(tokensDeclarationFormatter)
|
|
42
|
+
|
|
43
|
+
await sd.buildAllPlatforms()
|
|
44
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// scripts/generate-typography-tokens.js
|
|
2
|
+
// ---------------------------------------------------------
|
|
3
|
+
// Generate ALL typography tokens from primitives/font.json
|
|
4
|
+
// ---------------------------------------------------------
|
|
5
|
+
|
|
6
|
+
import fs from 'fs'
|
|
7
|
+
import path from 'path'
|
|
8
|
+
import { fileURLToPath } from 'url'
|
|
9
|
+
import { generateUtopiaScale } from '../src/utils'
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
12
|
+
const __dirname = path.dirname(__filename)
|
|
13
|
+
|
|
14
|
+
const INPUT_FILE = path.join(__dirname, `../src/tokens/1 - primitives/font.json`)
|
|
15
|
+
const PRIMITIVES_OUT = path.join(__dirname, `../src/tokens/1 - primitives/font-scale.json`)
|
|
16
|
+
const INTENT_OUT = path.join(__dirname, '../src/tokens/3 - intent/font.json')
|
|
17
|
+
|
|
18
|
+
// -----------------------------------
|
|
19
|
+
// Load primitive inputs for typography
|
|
20
|
+
// -----------------------------------
|
|
21
|
+
export function generateTypographyTokens() {
|
|
22
|
+
if (!fs.existsSync(INPUT_FILE)) {
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let configToken
|
|
27
|
+
try {
|
|
28
|
+
configToken = JSON.parse(fs.readFileSync(INPUT_FILE, 'utf8')).font
|
|
29
|
+
} catch {
|
|
30
|
+
process.exit(1)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const config = {
|
|
34
|
+
minFont: configToken.minFont?.value ?? 16,
|
|
35
|
+
maxFont: configToken.maxFont?.value ?? 20,
|
|
36
|
+
minViewport: configToken.minViewport?.value ?? 360,
|
|
37
|
+
maxViewport: configToken.maxViewport?.value ?? 1280,
|
|
38
|
+
scaleMin: configToken.scaleMin?.value ?? 1.2,
|
|
39
|
+
scaleMax: configToken.scaleMax?.value ?? 1.25,
|
|
40
|
+
steps: configToken.steps?.value ?? [0, 1, 2, 3, 4, 5, 6],
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// -----------------------------------
|
|
44
|
+
// Build Utopia scale
|
|
45
|
+
// -----------------------------------
|
|
46
|
+
|
|
47
|
+
const scale = generateUtopiaScale(config)
|
|
48
|
+
|
|
49
|
+
// -----------------------------------
|
|
50
|
+
// Output primitive scale tokens
|
|
51
|
+
// -----------------------------------
|
|
52
|
+
|
|
53
|
+
const primitives = {
|
|
54
|
+
font: {
|
|
55
|
+
scale: Object.fromEntries(Object.entries(scale).map(([step, value]) => [step, { value }])),
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// -----------------------------------
|
|
60
|
+
// Define intent tokens
|
|
61
|
+
// -----------------------------------
|
|
62
|
+
|
|
63
|
+
const intent = {
|
|
64
|
+
text: {
|
|
65
|
+
body: {
|
|
66
|
+
size: {
|
|
67
|
+
value: 'var(--font-scale-0)',
|
|
68
|
+
},
|
|
69
|
+
lineHeight: {
|
|
70
|
+
value: '1.5',
|
|
71
|
+
},
|
|
72
|
+
weight: {
|
|
73
|
+
value: 'var(--font-weight-regular)',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
caption: {
|
|
77
|
+
size: {
|
|
78
|
+
value: 'var(--font-scale--2)',
|
|
79
|
+
},
|
|
80
|
+
lineHeight: {
|
|
81
|
+
value: '1.4',
|
|
82
|
+
},
|
|
83
|
+
weight: {
|
|
84
|
+
value: 'var(--font-weight-regular)',
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
small: {
|
|
88
|
+
size: {
|
|
89
|
+
value: 'var(--font-scale--1)',
|
|
90
|
+
},
|
|
91
|
+
lineHeight: {
|
|
92
|
+
value: '1.4',
|
|
93
|
+
},
|
|
94
|
+
weight: {
|
|
95
|
+
value: 'var(--font-weight-regular)',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
heading: {
|
|
100
|
+
h1: {
|
|
101
|
+
size: {
|
|
102
|
+
value: 'var(--font-scale-4)',
|
|
103
|
+
},
|
|
104
|
+
lineHeight: {
|
|
105
|
+
value: '1.1',
|
|
106
|
+
},
|
|
107
|
+
weight: {
|
|
108
|
+
value: 'var(--font-weight-bold)',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
h2: {
|
|
112
|
+
size: {
|
|
113
|
+
value: 'var(--font-scale-3)',
|
|
114
|
+
},
|
|
115
|
+
lineHeight: {
|
|
116
|
+
value: '1.15',
|
|
117
|
+
},
|
|
118
|
+
weight: {
|
|
119
|
+
value: 'var(--font-weight-bold)',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// -----------------------------------
|
|
126
|
+
// Write JSON files
|
|
127
|
+
// -----------------------------------
|
|
128
|
+
|
|
129
|
+
function writeJSON(file: string, data: unknown) {
|
|
130
|
+
const dir = path.dirname(file)
|
|
131
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
|
|
132
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
writeJSON(PRIMITIVES_OUT, primitives)
|
|
136
|
+
// writeJSON(SEMANTIC_OUT, semantic);
|
|
137
|
+
writeJSON(INTENT_OUT, intent)
|
|
138
|
+
}
|