@bezel-labs/bezel-kit 0.1.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/LICENSE +93 -0
- package/README.md +69 -0
- package/dist/chunk-5EW7EW3R.js +370 -0
- package/dist/chunk-5EW7EW3R.js.map +1 -0
- package/dist/chunk-WLGTZBXW.js +139 -0
- package/dist/chunk-WLGTZBXW.js.map +1 -0
- package/dist/cli.cjs +567 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +93 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +401 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +133 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/node.cjs +530 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +73 -0
- package/dist/node.d.ts +73 -0
- package/dist/node.js +31 -0
- package/dist/node.js.map +1 -0
- package/package.json +76 -0
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
generateVariablesCss
|
|
4
|
+
} from "./chunk-WLGTZBXW.js";
|
|
5
|
+
import "./chunk-5EW7EW3R.js";
|
|
6
|
+
|
|
7
|
+
// src/cli.ts
|
|
8
|
+
import { existsSync } from "fs";
|
|
9
|
+
import { readFile } from "fs/promises";
|
|
10
|
+
import { pathToFileURL } from "url";
|
|
11
|
+
import { parseArgs } from "util";
|
|
12
|
+
import { resolve } from "path";
|
|
13
|
+
var USAGE = `bezel \u2014 convert a W3C Design Tokens (DTCG) file into a scoped variables.css
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
bezel build [options]
|
|
17
|
+
|
|
18
|
+
Reads design-tokens.json from the project root (the working directory).
|
|
19
|
+
|
|
20
|
+
Options:
|
|
21
|
+
-c, --config <path> Config file (.json or .js exporting BezelOptions)
|
|
22
|
+
--variables-output <path> Output CSS file (default: variables.css)
|
|
23
|
+
--contexts-output <path> Also write a generated TS module exporting CONTEXTS
|
|
24
|
+
--fonts-output <path> Also write a generated TS module exporting FONTS
|
|
25
|
+
--color <format> Color output: oklch | hex (default: oklch)
|
|
26
|
+
--unit <mode> Dimension unit: preserve | rem (default: preserve)
|
|
27
|
+
--stdout Print CSS to stdout instead of writing the file
|
|
28
|
+
--no-gitignore Don't create/update .gitignore for generated files
|
|
29
|
+
-h, --help Show this help
|
|
30
|
+
|
|
31
|
+
A bezel.json file in the working directory is loaded automatically when -c is omitted.
|
|
32
|
+
`;
|
|
33
|
+
var DEFAULT_CONFIG_FILE = "bezel.json";
|
|
34
|
+
async function loadConfig(path) {
|
|
35
|
+
const abs = resolve(process.cwd(), path);
|
|
36
|
+
if (/\.json$/.test(abs)) {
|
|
37
|
+
return JSON.parse(await readFile(abs, "utf8"));
|
|
38
|
+
}
|
|
39
|
+
const mod = await import(pathToFileURL(abs).href);
|
|
40
|
+
return mod.default ?? mod;
|
|
41
|
+
}
|
|
42
|
+
async function main(argv) {
|
|
43
|
+
const { values, positionals } = parseArgs({
|
|
44
|
+
args: argv,
|
|
45
|
+
allowPositionals: true,
|
|
46
|
+
options: {
|
|
47
|
+
config: { type: "string", short: "c" },
|
|
48
|
+
"variables-output": { type: "string" },
|
|
49
|
+
"contexts-output": { type: "string" },
|
|
50
|
+
"fonts-output": { type: "string" },
|
|
51
|
+
color: { type: "string" },
|
|
52
|
+
unit: { type: "string" },
|
|
53
|
+
stdout: { type: "boolean" },
|
|
54
|
+
"no-gitignore": { type: "boolean" },
|
|
55
|
+
help: { type: "boolean", short: "h" }
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
if (values.help || positionals[0] === "help") {
|
|
59
|
+
process.stdout.write(USAGE);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const command = positionals[0] ?? "build";
|
|
63
|
+
if (command !== "build") {
|
|
64
|
+
process.stderr.write(`bezel: unknown command "${command}".
|
|
65
|
+
|
|
66
|
+
${USAGE}`);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const configPath = values.config ?? (existsSync(resolve(process.cwd(), DEFAULT_CONFIG_FILE)) ? DEFAULT_CONFIG_FILE : void 0);
|
|
71
|
+
const fileConfig = configPath ? await loadConfig(configPath) : {};
|
|
72
|
+
const options = { ...fileConfig };
|
|
73
|
+
if (values["variables-output"]) options.variablesOutput = values["variables-output"];
|
|
74
|
+
if (values["contexts-output"]) options.contextsOutput = values["contexts-output"];
|
|
75
|
+
if (values["fonts-output"]) options.fontsOutput = values["fonts-output"];
|
|
76
|
+
if (values.color) options.colorFormat = values.color;
|
|
77
|
+
if (values.unit) options.dimensionUnit = values.unit;
|
|
78
|
+
if (values.stdout) options.write = false;
|
|
79
|
+
if (values["no-gitignore"]) options.gitignore = false;
|
|
80
|
+
const css = await generateVariablesCss(options);
|
|
81
|
+
if (values.stdout) {
|
|
82
|
+
process.stdout.write(css);
|
|
83
|
+
} else {
|
|
84
|
+
process.stderr.write(`bezel: wrote ${options.variablesOutput ?? "variables.css"}
|
|
85
|
+
`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
main(process.argv.slice(2)).catch((err) => {
|
|
89
|
+
process.stderr.write(`${err instanceof Error ? err.message : String(err)}
|
|
90
|
+
`);
|
|
91
|
+
process.exitCode = 1;
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { pathToFileURL } from \"node:url\"\nimport { parseArgs } from \"node:util\"\nimport { resolve } from \"node:path\"\nimport { generateVariablesCss } from \"./node\"\nimport type { BezelOptions } from \"./config\"\n\nconst USAGE = `bezel — convert a W3C Design Tokens (DTCG) file into a scoped variables.css\n\nUsage:\n bezel build [options]\n\nReads design-tokens.json from the project root (the working directory).\n\nOptions:\n -c, --config <path> Config file (.json or .js exporting BezelOptions)\n --variables-output <path> Output CSS file (default: variables.css)\n --contexts-output <path> Also write a generated TS module exporting CONTEXTS\n --fonts-output <path> Also write a generated TS module exporting FONTS\n --color <format> Color output: oklch | hex (default: oklch)\n --unit <mode> Dimension unit: preserve | rem (default: preserve)\n --stdout Print CSS to stdout instead of writing the file\n --no-gitignore Don't create/update .gitignore for generated files\n -h, --help Show this help\n\nA bezel.json file in the working directory is loaded automatically when -c is omitted.\n`\n\n/** Default config file auto-loaded from the working directory when no -c is given. */\nconst DEFAULT_CONFIG_FILE = \"bezel.json\"\n\n/** Load options from a `.json` or `.js`/`.mjs` config file. */\nasync function loadConfig(path: string): Promise<BezelOptions> {\n const abs = resolve(process.cwd(), path)\n if (/\\.json$/.test(abs)) {\n return JSON.parse(await readFile(abs, \"utf8\")) as BezelOptions\n }\n const mod = (await import(pathToFileURL(abs).href)) as {\n default?: BezelOptions\n } & BezelOptions\n return (mod.default ?? mod) as BezelOptions\n}\n\nasync function main(argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n config: { type: \"string\", short: \"c\" },\n \"variables-output\": { type: \"string\" },\n \"contexts-output\": { type: \"string\" },\n \"fonts-output\": { type: \"string\" },\n color: { type: \"string\" },\n unit: { type: \"string\" },\n stdout: { type: \"boolean\" },\n \"no-gitignore\": { type: \"boolean\" },\n help: { type: \"boolean\", short: \"h\" },\n },\n })\n\n if (values.help || positionals[0] === \"help\") {\n process.stdout.write(USAGE)\n return\n }\n\n const command = positionals[0] ?? \"build\"\n if (command !== \"build\") {\n process.stderr.write(`bezel: unknown command \"${command}\".\\n\\n${USAGE}`)\n process.exitCode = 1\n return\n }\n\n const configPath =\n values.config ??\n (existsSync(resolve(process.cwd(), DEFAULT_CONFIG_FILE))\n ? DEFAULT_CONFIG_FILE\n : undefined)\n const fileConfig = configPath ? await loadConfig(configPath) : {}\n\n const options: BezelOptions = { ...fileConfig }\n if (values[\"variables-output\"]) options.variablesOutput = values[\"variables-output\"]\n if (values[\"contexts-output\"]) options.contextsOutput = values[\"contexts-output\"]\n if (values[\"fonts-output\"]) options.fontsOutput = values[\"fonts-output\"]\n if (values.color) options.colorFormat = values.color as BezelOptions[\"colorFormat\"]\n if (values.unit) options.dimensionUnit = values.unit as BezelOptions[\"dimensionUnit\"]\n if (values.stdout) options.write = false\n if (values[\"no-gitignore\"]) options.gitignore = false\n\n const css = await generateVariablesCss(options)\n\n if (values.stdout) {\n process.stdout.write(css)\n } else {\n process.stderr.write(`bezel: wrote ${options.variablesOutput ?? \"variables.css\"}\\n`)\n }\n}\n\nmain(process.argv.slice(2)).catch((err: unknown) => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n process.exitCode = 1\n})\n"],"mappings":";;;;;;;AACA,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AAIxB,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBd,IAAM,sBAAsB;AAG5B,eAAe,WAAW,MAAqC;AAC7D,QAAM,MAAM,QAAQ,QAAQ,IAAI,GAAG,IAAI;AACvC,MAAI,UAAU,KAAK,GAAG,GAAG;AACvB,WAAO,KAAK,MAAM,MAAM,SAAS,KAAK,MAAM,CAAC;AAAA,EAC/C;AACA,QAAM,MAAO,MAAM,OAAO,cAAc,GAAG,EAAE;AAG7C,SAAQ,IAAI,WAAW;AACzB;AAEA,eAAe,KAAK,MAA+B;AACjD,QAAM,EAAE,QAAQ,YAAY,IAAI,UAAU;AAAA,IACxC,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,SAAS;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,OAAO,IAAI;AAAA,MACrC,oBAAoB,EAAE,MAAM,SAAS;AAAA,MACrC,mBAAmB,EAAE,MAAM,SAAS;AAAA,MACpC,gBAAgB,EAAE,MAAM,SAAS;AAAA,MACjC,OAAO,EAAE,MAAM,SAAS;AAAA,MACxB,MAAM,EAAE,MAAM,SAAS;AAAA,MACvB,QAAQ,EAAE,MAAM,UAAU;AAAA,MAC1B,gBAAgB,EAAE,MAAM,UAAU;AAAA,MAClC,MAAM,EAAE,MAAM,WAAW,OAAO,IAAI;AAAA,IACtC;AAAA,EACF,CAAC;AAED,MAAI,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ;AAC5C,YAAQ,OAAO,MAAM,KAAK;AAC1B;AAAA,EACF;AAEA,QAAM,UAAU,YAAY,CAAC,KAAK;AAClC,MAAI,YAAY,SAAS;AACvB,YAAQ,OAAO,MAAM,2BAA2B,OAAO;AAAA;AAAA,EAAS,KAAK,EAAE;AACvE,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,aACJ,OAAO,WACN,WAAW,QAAQ,QAAQ,IAAI,GAAG,mBAAmB,CAAC,IACnD,sBACA;AACN,QAAM,aAAa,aAAa,MAAM,WAAW,UAAU,IAAI,CAAC;AAEhE,QAAM,UAAwB,EAAE,GAAG,WAAW;AAC9C,MAAI,OAAO,kBAAkB,EAAG,SAAQ,kBAAkB,OAAO,kBAAkB;AACnF,MAAI,OAAO,iBAAiB,EAAG,SAAQ,iBAAiB,OAAO,iBAAiB;AAChF,MAAI,OAAO,cAAc,EAAG,SAAQ,cAAc,OAAO,cAAc;AACvE,MAAI,OAAO,MAAO,SAAQ,cAAc,OAAO;AAC/C,MAAI,OAAO,KAAM,SAAQ,gBAAgB,OAAO;AAChD,MAAI,OAAO,OAAQ,SAAQ,QAAQ;AACnC,MAAI,OAAO,cAAc,EAAG,SAAQ,YAAY;AAEhD,QAAM,MAAM,MAAM,qBAAqB,OAAO;AAE9C,MAAI,OAAO,QAAQ;AACjB,YAAQ,OAAO,MAAM,GAAG;AAAA,EAC1B,OAAO;AACL,YAAQ,OAAO,MAAM,gBAAgB,QAAQ,mBAAmB,eAAe;AAAA,CAAI;AAAA,EACrF;AACF;AAEA,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,QAAiB;AAClD,UAAQ,OAAO,MAAM,GAAG,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AAC5E,UAAQ,WAAW;AACrB,CAAC;","names":[]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
DEFAULT_CONTEXTS: () => DEFAULT_CONTEXTS,
|
|
24
|
+
DEFAULT_CONTEXT_NAME: () => DEFAULT_CONTEXT_NAME,
|
|
25
|
+
DEFAULT_NAME_EXTENSION: () => DEFAULT_NAME_EXTENSION,
|
|
26
|
+
emitCss: () => emitCss,
|
|
27
|
+
formatContextsModule: () => formatContextsModule,
|
|
28
|
+
formatFontsModule: () => formatFontsModule,
|
|
29
|
+
getContexts: () => getContexts,
|
|
30
|
+
getFonts: () => getFonts,
|
|
31
|
+
resolveCssOptions: () => resolveCssOptions,
|
|
32
|
+
tokensToCss: () => tokensToCss
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
|
+
|
|
36
|
+
// src/collapse.ts
|
|
37
|
+
var ROOT_CONTEXT = "$root";
|
|
38
|
+
function isObject(v) {
|
|
39
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
40
|
+
}
|
|
41
|
+
function isContextWrapper(v) {
|
|
42
|
+
return isObject(v) && "$value" in v;
|
|
43
|
+
}
|
|
44
|
+
function isMetaKey(key) {
|
|
45
|
+
return key === "$type" || key === "$description" || key === "$extensions" || key === "$value";
|
|
46
|
+
}
|
|
47
|
+
function flattenForContext(tokens, context) {
|
|
48
|
+
const out = /* @__PURE__ */ new Map();
|
|
49
|
+
const walk = (node, path, inheritedType) => {
|
|
50
|
+
const type = typeof node.$type === "string" ? node.$type : inheritedType;
|
|
51
|
+
if ("$value" in node) {
|
|
52
|
+
out.set(path, {
|
|
53
|
+
path,
|
|
54
|
+
value: node.$value,
|
|
55
|
+
type,
|
|
56
|
+
extensions: node.$extensions
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const wrapperKeys = Object.keys(node).filter((k) => !isMetaKey(k) && isContextWrapper(node[k]));
|
|
61
|
+
if (wrapperKeys.length > 0) {
|
|
62
|
+
const chosen = node[context] ?? node[ROOT_CONTEXT] ?? node[wrapperKeys[0]];
|
|
63
|
+
out.set(path, {
|
|
64
|
+
path,
|
|
65
|
+
value: chosen.$value,
|
|
66
|
+
type,
|
|
67
|
+
extensions: node.$extensions
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
for (const key of Object.keys(node)) {
|
|
72
|
+
if (isMetaKey(key)) continue;
|
|
73
|
+
const child = node[key];
|
|
74
|
+
if (isObject(child)) {
|
|
75
|
+
walk(child, path ? `${path}.${key}` : key, type);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
walk(tokens, "", void 0);
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/name.ts
|
|
84
|
+
var DROPPED_PREFIXES = /* @__PURE__ */ new Set(["base", "semantic"]);
|
|
85
|
+
var DROPPED_SUFFIXES = /* @__PURE__ */ new Set(["default", "$root"]);
|
|
86
|
+
function exportNames(token, nameExtension) {
|
|
87
|
+
const ext = token.extensions?.[nameExtension];
|
|
88
|
+
if (ext && typeof ext === "object" && "exportName" in ext) {
|
|
89
|
+
const names = ext.exportName;
|
|
90
|
+
if (Array.isArray(names)) return names.filter((n) => typeof n === "string");
|
|
91
|
+
}
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
function usesExportNames(tokens, nameExtension) {
|
|
95
|
+
for (const token of tokens) {
|
|
96
|
+
if (exportNames(token, nameExtension) !== void 0) return true;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
function nameFromPath(path) {
|
|
101
|
+
const segments = path.split(".");
|
|
102
|
+
while (segments.length > 1 && DROPPED_PREFIXES.has(segments[0])) segments.shift();
|
|
103
|
+
while (segments.length > 1 && DROPPED_SUFFIXES.has(segments[segments.length - 1])) {
|
|
104
|
+
segments.pop();
|
|
105
|
+
}
|
|
106
|
+
return segments.join("-");
|
|
107
|
+
}
|
|
108
|
+
function cssNames(token, nameExtension, useExportName) {
|
|
109
|
+
if (useExportName) {
|
|
110
|
+
const names = exportNames(token, nameExtension);
|
|
111
|
+
if (!names) return [];
|
|
112
|
+
return names.filter((n) => n.length > 0);
|
|
113
|
+
}
|
|
114
|
+
return [nameFromPath(token.path)];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/resolve.ts
|
|
118
|
+
var REFERENCE_RE = /^\{([^{}]+)\}$/;
|
|
119
|
+
function aliasTarget(value) {
|
|
120
|
+
if (typeof value !== "string") return null;
|
|
121
|
+
const match = REFERENCE_RE.exec(value.trim());
|
|
122
|
+
return match ? match[1].trim() : null;
|
|
123
|
+
}
|
|
124
|
+
function resolveReferences(tokens) {
|
|
125
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
126
|
+
const resolveValue = (value, seen) => {
|
|
127
|
+
const target = aliasTarget(value);
|
|
128
|
+
if (target === null) return value;
|
|
129
|
+
if (resolved.has(target)) return resolved.get(target);
|
|
130
|
+
if (seen.has(target)) {
|
|
131
|
+
throw new Error(`bezel: circular token reference detected at "{${target}}".`);
|
|
132
|
+
}
|
|
133
|
+
const token = tokens.get(target);
|
|
134
|
+
if (!token) {
|
|
135
|
+
throw new Error(`bezel: unresolved token reference "{${target}}".`);
|
|
136
|
+
}
|
|
137
|
+
seen.add(target);
|
|
138
|
+
const value2 = resolveValue(token.value, seen);
|
|
139
|
+
seen.delete(target);
|
|
140
|
+
resolved.set(target, value2);
|
|
141
|
+
return value2;
|
|
142
|
+
};
|
|
143
|
+
for (const token of tokens.values()) {
|
|
144
|
+
token.value = resolveValue(token.value, /* @__PURE__ */ new Set());
|
|
145
|
+
}
|
|
146
|
+
return tokens;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/serialize.ts
|
|
150
|
+
function isObject2(v) {
|
|
151
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
152
|
+
}
|
|
153
|
+
function isColor(v) {
|
|
154
|
+
return isObject2(v) && "colorSpace" in v && Array.isArray(v["components"]);
|
|
155
|
+
}
|
|
156
|
+
function isDimension(v) {
|
|
157
|
+
return isObject2(v) && typeof v["value"] === "number" && "unit" in v;
|
|
158
|
+
}
|
|
159
|
+
function round(n, dp) {
|
|
160
|
+
const f = 10 ** dp;
|
|
161
|
+
return Math.round(n * f) / f;
|
|
162
|
+
}
|
|
163
|
+
function serializeColor(color, format) {
|
|
164
|
+
if (format === "hex" && color.hex) return color.hex.toLowerCase();
|
|
165
|
+
if (color.colorSpace === "oklch") {
|
|
166
|
+
const [l = 0, c = 0, h = 0] = color.components;
|
|
167
|
+
const base = `oklch(${round(l, 4)} ${round(c, 4)} ${round(h, 3)})`;
|
|
168
|
+
if (color.alpha !== void 0 && color.alpha < 1) {
|
|
169
|
+
return `oklch(${round(l, 4)} ${round(c, 4)} ${round(h, 3)} / ${round(color.alpha, 4)})`;
|
|
170
|
+
}
|
|
171
|
+
return base;
|
|
172
|
+
}
|
|
173
|
+
if (color.hex) return color.hex.toLowerCase();
|
|
174
|
+
return `color(${color.colorSpace} ${color.components.map((n) => round(n, 4)).join(" ")})`;
|
|
175
|
+
}
|
|
176
|
+
function serializeDimension(dim, unit) {
|
|
177
|
+
if (unit === "rem" && dim.unit === "px") {
|
|
178
|
+
return `${round(dim.value / 16, 4)}rem`;
|
|
179
|
+
}
|
|
180
|
+
return `${dim.value}${dim.unit}`;
|
|
181
|
+
}
|
|
182
|
+
function quoteFamily(name) {
|
|
183
|
+
const trimmed = name.trim();
|
|
184
|
+
if (/^['"].*['"]$/.test(trimmed)) return trimmed;
|
|
185
|
+
return /\s/.test(trimmed) ? `"${trimmed}"` : trimmed;
|
|
186
|
+
}
|
|
187
|
+
function serializeValue(value, options) {
|
|
188
|
+
if (isColor(value)) return serializeColor(value, options.colorFormat);
|
|
189
|
+
if (isDimension(value)) return serializeDimension(value, options.dimensionUnit);
|
|
190
|
+
if (Array.isArray(value)) {
|
|
191
|
+
return value.map((v) => quoteFamily(String(v))).join(", ");
|
|
192
|
+
}
|
|
193
|
+
if (typeof value === "number") return String(value);
|
|
194
|
+
const str = String(value);
|
|
195
|
+
if (/\s/.test(str) && !str.includes(",") && !/[()]/.test(str)) {
|
|
196
|
+
return quoteFamily(str);
|
|
197
|
+
}
|
|
198
|
+
return str;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/emit.ts
|
|
202
|
+
function buildContextVars(tokens, context, useExportName, options) {
|
|
203
|
+
const flat = resolveReferences(flattenForContext(tokens, context));
|
|
204
|
+
const vars = /* @__PURE__ */ new Map();
|
|
205
|
+
for (const token of flat.values()) {
|
|
206
|
+
const names = cssNames(token, options.nameExtension, useExportName);
|
|
207
|
+
if (names.length === 0) continue;
|
|
208
|
+
const value = serializeValue(token.value, options);
|
|
209
|
+
for (const name of names) vars.set(name, value);
|
|
210
|
+
}
|
|
211
|
+
return vars;
|
|
212
|
+
}
|
|
213
|
+
function renderBlock(selector, vars) {
|
|
214
|
+
const lines = [...vars].map(([name, value]) => ` --${name}: ${value};`);
|
|
215
|
+
if (lines.length === 0) return "";
|
|
216
|
+
return `${selector} {
|
|
217
|
+
${lines.join("\n")}
|
|
218
|
+
}`;
|
|
219
|
+
}
|
|
220
|
+
function emitCss(tokens, options) {
|
|
221
|
+
const contextNames = Object.keys(options.contexts);
|
|
222
|
+
const useExportName = usesExportNames(
|
|
223
|
+
flattenForContext(tokens, contextNames[0]).values(),
|
|
224
|
+
options.nameExtension
|
|
225
|
+
);
|
|
226
|
+
const [baseContext, ...overrideContexts] = contextNames;
|
|
227
|
+
const baseVars = buildContextVars(tokens, baseContext, useExportName, options);
|
|
228
|
+
const blocks = [renderBlock(options.contexts[baseContext], baseVars)];
|
|
229
|
+
for (const context of overrideContexts) {
|
|
230
|
+
const vars = buildContextVars(tokens, context, useExportName, options);
|
|
231
|
+
const overrides = [...vars].filter(([name, value]) => baseVars.get(name) !== value);
|
|
232
|
+
const block = renderBlock(options.contexts[context], overrides);
|
|
233
|
+
if (block) blocks.push(block);
|
|
234
|
+
}
|
|
235
|
+
const header = "/* Generated by bezel \u2014 do not edit by hand. */\n/* Run `npm run tokens` (or `bezel build`) to regenerate. */\n";
|
|
236
|
+
return `${header}
|
|
237
|
+
${blocks.filter(Boolean).join("\n\n")}
|
|
238
|
+
`;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/defaults.ts
|
|
242
|
+
var DEFAULT_CONTEXTS = {
|
|
243
|
+
$root: ":root",
|
|
244
|
+
dark: ".dark",
|
|
245
|
+
light: ".light"
|
|
246
|
+
};
|
|
247
|
+
var DEFAULT_NAME_EXTENSION = "com.tokendesigner.app";
|
|
248
|
+
|
|
249
|
+
// src/options.ts
|
|
250
|
+
function resolveCssOptions(options = {}) {
|
|
251
|
+
const contexts = options.contexts ?? DEFAULT_CONTEXTS;
|
|
252
|
+
if (Object.keys(contexts).length === 0) {
|
|
253
|
+
throw new Error("bezel: `contexts` must define at least one context.");
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
contexts,
|
|
257
|
+
colorFormat: options.colorFormat ?? "oklch",
|
|
258
|
+
dimensionUnit: options.dimensionUnit ?? "preserve",
|
|
259
|
+
nameExtension: options.nameExtension ?? DEFAULT_NAME_EXTENSION
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// src/contexts.ts
|
|
264
|
+
var DEFAULT_CONTEXT_NAME = "default";
|
|
265
|
+
function isObject3(v) {
|
|
266
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
267
|
+
}
|
|
268
|
+
function isContextWrapper2(v) {
|
|
269
|
+
return isObject3(v) && "$value" in v;
|
|
270
|
+
}
|
|
271
|
+
function getContexts(tokens, rootName = DEFAULT_CONTEXT_NAME) {
|
|
272
|
+
const order = [];
|
|
273
|
+
const seen = /* @__PURE__ */ new Set();
|
|
274
|
+
const walk = (node) => {
|
|
275
|
+
if (ROOT_CONTEXT in node && isContextWrapper2(node[ROOT_CONTEXT])) {
|
|
276
|
+
for (const key of Object.keys(node)) {
|
|
277
|
+
if (key.startsWith("$") && key !== ROOT_CONTEXT) continue;
|
|
278
|
+
if (isContextWrapper2(node[key]) && !seen.has(key)) {
|
|
279
|
+
seen.add(key);
|
|
280
|
+
order.push(key);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
for (const key of Object.keys(node)) {
|
|
286
|
+
if (key.startsWith("$")) continue;
|
|
287
|
+
const child = node[key];
|
|
288
|
+
if (isObject3(child)) walk(child);
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
walk(tokens);
|
|
292
|
+
const mapped = order.map((k) => k === ROOT_CONTEXT ? rootName : k);
|
|
293
|
+
return [.../* @__PURE__ */ new Set([rootName, ...mapped])];
|
|
294
|
+
}
|
|
295
|
+
function formatContextsModule(contexts) {
|
|
296
|
+
const list = contexts.map((c) => JSON.stringify(c)).join(", ");
|
|
297
|
+
return `/* Generated by bezel \u2014 do not edit by hand. */
|
|
298
|
+
/* Run \`npm run tokens\` (or \`bezel build\`) to regenerate. */
|
|
299
|
+
|
|
300
|
+
export const CONTEXTS = [${list}] as const
|
|
301
|
+
|
|
302
|
+
export type Context = (typeof CONTEXTS)[number]
|
|
303
|
+
`;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/fonts.ts
|
|
307
|
+
var GENERIC_FAMILIES = /* @__PURE__ */ new Set([
|
|
308
|
+
"serif",
|
|
309
|
+
"sans-serif",
|
|
310
|
+
"monospace",
|
|
311
|
+
"cursive",
|
|
312
|
+
"fantasy",
|
|
313
|
+
"system-ui",
|
|
314
|
+
"ui-serif",
|
|
315
|
+
"ui-sans-serif",
|
|
316
|
+
"ui-monospace",
|
|
317
|
+
"ui-rounded",
|
|
318
|
+
"math",
|
|
319
|
+
"emoji",
|
|
320
|
+
"fangsong",
|
|
321
|
+
"inherit",
|
|
322
|
+
"initial",
|
|
323
|
+
"unset"
|
|
324
|
+
]);
|
|
325
|
+
var DEFAULT_WEIGHT = 400;
|
|
326
|
+
function primaryFamily(value) {
|
|
327
|
+
const candidates = Array.isArray(value) ? value : [value];
|
|
328
|
+
for (const candidate of candidates) {
|
|
329
|
+
if (typeof candidate !== "string") continue;
|
|
330
|
+
const name = candidate.trim().replace(/^['"]|['"]$/g, "");
|
|
331
|
+
if (name && !GENERIC_FAMILIES.has(name.toLowerCase())) return name;
|
|
332
|
+
}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
function parentPath(path) {
|
|
336
|
+
const i = path.lastIndexOf(".");
|
|
337
|
+
return i === -1 ? "" : path.slice(0, i);
|
|
338
|
+
}
|
|
339
|
+
function getFonts(tokens) {
|
|
340
|
+
const flat = resolveReferences(flattenForContext(tokens, ROOT_CONTEXT));
|
|
341
|
+
const families = /* @__PURE__ */ new Set();
|
|
342
|
+
const familyByParent = /* @__PURE__ */ new Map();
|
|
343
|
+
const weightByParent = /* @__PURE__ */ new Map();
|
|
344
|
+
for (const token of flat.values()) {
|
|
345
|
+
if (token.type === "fontFamily") {
|
|
346
|
+
const family = primaryFamily(token.value);
|
|
347
|
+
if (family) {
|
|
348
|
+
families.add(family);
|
|
349
|
+
familyByParent.set(parentPath(token.path), family);
|
|
350
|
+
}
|
|
351
|
+
} else if (token.type === "fontWeight" && typeof token.value === "number") {
|
|
352
|
+
weightByParent.set(parentPath(token.path), token.value);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const weightsByFamily = /* @__PURE__ */ new Map();
|
|
356
|
+
for (const [parent, family] of familyByParent) {
|
|
357
|
+
const weight = weightByParent.get(parent);
|
|
358
|
+
if (weight === void 0) continue;
|
|
359
|
+
const set = weightsByFamily.get(family) ?? /* @__PURE__ */ new Set();
|
|
360
|
+
set.add(weight);
|
|
361
|
+
weightsByFamily.set(family, set);
|
|
362
|
+
}
|
|
363
|
+
return [...families].sort().map((family) => {
|
|
364
|
+
const weights = weightsByFamily.get(family);
|
|
365
|
+
return {
|
|
366
|
+
family,
|
|
367
|
+
weights: weights ? [...weights].sort((a, b) => a - b) : [DEFAULT_WEIGHT]
|
|
368
|
+
};
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
function formatFontsModule(fonts) {
|
|
372
|
+
const entries = fonts.map((f) => ` { family: ${JSON.stringify(f.family)}, weights: [${f.weights.join(", ")}] },`).join("\n");
|
|
373
|
+
return `/* Generated by bezel \u2014 do not edit by hand. */
|
|
374
|
+
/* Run \`npm run tokens\` (or \`bezel build\`) to regenerate. */
|
|
375
|
+
|
|
376
|
+
export const FONTS = [
|
|
377
|
+
${entries}
|
|
378
|
+
] as const
|
|
379
|
+
|
|
380
|
+
export type FontDef = { family: string; weights: number[] }
|
|
381
|
+
`;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/index.ts
|
|
385
|
+
function tokensToCss(tokens, options = {}) {
|
|
386
|
+
return emitCss(tokens, resolveCssOptions(options));
|
|
387
|
+
}
|
|
388
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
389
|
+
0 && (module.exports = {
|
|
390
|
+
DEFAULT_CONTEXTS,
|
|
391
|
+
DEFAULT_CONTEXT_NAME,
|
|
392
|
+
DEFAULT_NAME_EXTENSION,
|
|
393
|
+
emitCss,
|
|
394
|
+
formatContextsModule,
|
|
395
|
+
formatFontsModule,
|
|
396
|
+
getContexts,
|
|
397
|
+
getFonts,
|
|
398
|
+
resolveCssOptions,
|
|
399
|
+
tokensToCss
|
|
400
|
+
});
|
|
401
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/collapse.ts","../src/name.ts","../src/resolve.ts","../src/serialize.ts","../src/emit.ts","../src/defaults.ts","../src/options.ts","../src/contexts.ts","../src/fonts.ts"],"sourcesContent":["/**\n * bezel — isomorphic entry.\n *\n * The pure transform core: convert an in-memory W3C Design Tokens (DTCG) object\n * into a scoped `variables.css` string. Imports no `node:*`, so it runs anywhere\n * — browser, edge, Node. For the filesystem/CLI conveniences (reading a tokens\n * file, writing outputs), import from `bezel/node`.\n */\nimport { emitCss } from \"./emit\"\nimport { resolveCssOptions, type CssOptions } from \"./options\"\nimport type { DtcgNode } from \"./types\"\n\nexport type { CssOptions, ResolvedCssOptions } from \"./options\"\nexport type { DtcgNode, FlatToken, TokenValue, ColorValue, DimensionValue } from \"./types\"\nexport { DEFAULT_CONTEXTS, DEFAULT_NAME_EXTENSION } from \"./defaults\"\nexport { emitCss } from \"./emit\"\nexport { resolveCssOptions } from \"./options\"\nexport { getContexts, formatContextsModule, DEFAULT_CONTEXT_NAME } from \"./contexts\"\nexport { getFonts, formatFontsModule } from \"./fonts\"\nexport type { FontDef } from \"./fonts\"\n\n/**\n * Convert a DTCG token object into a scoped `variables.css` string.\n *\n * Resolves each configured context (with `$root` fallback and reference\n * resolution) and emits one CSS scope per context — the base context in full,\n * others as override-only blocks. Pure: no filesystem access.\n *\n * @example\n * const css = tokensToCss(tokens)\n *\n * @example\n * const css = tokensToCss(tokens, { colorFormat: \"hex\", contexts: { $root: \":root\" } })\n */\nexport function tokensToCss(tokens: DtcgNode, options: CssOptions = {}): string {\n return emitCss(tokens, resolveCssOptions(options))\n}\n","import type { DtcgNode, FlatToken, TokenValue } from \"./types\"\n\n/** The W3C \"root token\" key — the base value of a group / logical token. */\nexport const ROOT_CONTEXT = \"$root\"\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v)\n}\n\n/** A \"context wrapper\" is a child object that directly holds a `$value` (e.g. `dark`, `light`, `$root`). */\nfunction isContextWrapper(v: unknown): v is DtcgNode {\n return isObject(v) && \"$value\" in v\n}\n\n/** Keys that are DTCG metadata, never traversed as child tokens/contexts. */\nfunction isMetaKey(key: string): boolean {\n return key === \"$type\" || key === \"$description\" || key === \"$extensions\" || key === \"$value\"\n}\n\n/**\n * Collapse a DTCG token tree to the single value that applies for `context`, and\n * flatten it to a map of dot-path → {@link FlatToken}.\n *\n * Handles three node shapes:\n * - **Simple token** — a node with a direct `$value` (context-invariant).\n * - **Logical token** — a node whose children include context wrappers (one of\n * which is `$root`). The value for `context` is picked, falling back to `$root`.\n * - **Group** — anything else; recursed into.\n *\n * `$type` is inherited from the nearest ancestor that declares one.\n */\nexport function flattenForContext(tokens: DtcgNode, context: string): Map<string, FlatToken> {\n const out = new Map<string, FlatToken>()\n\n const walk = (node: DtcgNode, path: string, inheritedType: string | undefined): void => {\n const type = typeof node.$type === \"string\" ? node.$type : inheritedType\n\n // Simple token: direct $value.\n if (\"$value\" in node) {\n out.set(path, {\n path,\n value: node.$value as TokenValue,\n type,\n extensions: node.$extensions,\n })\n return\n }\n\n // Logical token: has context-wrapper children (dark/light/$root).\n const wrapperKeys = Object.keys(node).filter((k) => !isMetaKey(k) && isContextWrapper(node[k]))\n if (wrapperKeys.length > 0) {\n const chosen =\n (node[context] as DtcgNode | undefined) ??\n (node[ROOT_CONTEXT] as DtcgNode | undefined) ??\n (node[wrapperKeys[0]!] as DtcgNode)\n out.set(path, {\n path,\n value: chosen.$value as TokenValue,\n type,\n extensions: node.$extensions,\n })\n return\n }\n\n // Group: recurse into non-meta children.\n for (const key of Object.keys(node)) {\n if (isMetaKey(key)) continue\n const child = node[key]\n if (isObject(child)) {\n walk(child as DtcgNode, path ? `${path}.${key}` : key, type)\n }\n }\n }\n\n walk(tokens, \"\", undefined)\n return out\n}\n","import type { FlatToken } from \"./types\"\n\n/** Leading path segments dropped when deriving a CSS name from a token path. */\nconst DROPPED_PREFIXES = new Set([\"base\", \"semantic\"])\n/** Trailing path segments dropped (a group's \"default\"/root token maps to the bare group name). */\nconst DROPPED_SUFFIXES = new Set([\"default\", \"$root\"])\n\nfunction exportNames(token: FlatToken, nameExtension: string): string[] | undefined {\n const ext = token.extensions?.[nameExtension]\n if (ext && typeof ext === \"object\" && \"exportName\" in ext) {\n const names = (ext as { exportName: unknown }).exportName\n if (Array.isArray(names)) return names.filter((n): n is string => typeof n === \"string\")\n }\n return undefined\n}\n\n/** True if any token in the map declares an `exportName` under `nameExtension`. */\nexport function usesExportNames(\n tokens: Iterable<FlatToken>,\n nameExtension: string,\n): boolean {\n for (const token of tokens) {\n if (exportNames(token, nameExtension) !== undefined) return true\n }\n return false\n}\n\n/** Derive a CSS variable name from a dot-path (fallback when no `exportName` exists). */\nexport function nameFromPath(path: string): string {\n const segments = path.split(\".\")\n while (segments.length > 1 && DROPPED_PREFIXES.has(segments[0]!)) segments.shift()\n while (segments.length > 1 && DROPPED_SUFFIXES.has(segments[segments.length - 1]!)) {\n segments.pop()\n }\n return segments.join(\"-\")\n}\n\n/**\n * Resolve the CSS variable name(s) a token emits (without the leading `--`).\n *\n * - In **exportName mode** (`useExportName`), names come solely from the token's\n * `exportName` array. A token without one — or with only empty strings — emits\n * nothing (it exists purely as a reference target). One token may emit many names.\n * - Otherwise (generic DTCG), the name is derived from the token's path.\n */\nexport function cssNames(\n token: FlatToken,\n nameExtension: string,\n useExportName: boolean,\n): string[] {\n if (useExportName) {\n const names = exportNames(token, nameExtension)\n if (!names) return []\n return names.filter((n) => n.length > 0)\n }\n return [nameFromPath(token.path)]\n}\n","import type { FlatToken, TokenValue } from \"./types\"\n\nconst REFERENCE_RE = /^\\{([^{}]+)\\}$/\n\n/** Returns the referenced path if `value` is a whole-value DTCG alias `\"{a.b.c}\"`, else `null`. */\nexport function aliasTarget(value: TokenValue): string | null {\n if (typeof value !== \"string\") return null\n const match = REFERENCE_RE.exec(value.trim())\n return match ? match[1]!.trim() : null\n}\n\n/**\n * Resolve whole-value references (`\"{a.b.c}\"`) in a flattened, single-context token\n * map, in place. Because the map was collapsed for one context, following an alias\n * yields that context's value (with `$root` fallback already applied during collapse).\n *\n * Multi-hop aliases are followed, results memoized, and cycles guarded against.\n */\nexport function resolveReferences(tokens: Map<string, FlatToken>): Map<string, FlatToken> {\n const resolved = new Map<string, TokenValue>()\n\n const resolveValue = (value: TokenValue, seen: Set<string>): TokenValue => {\n const target = aliasTarget(value)\n if (target === null) return value\n\n if (resolved.has(target)) return resolved.get(target)!\n if (seen.has(target)) {\n throw new Error(`bezel: circular token reference detected at \"{${target}}\".`)\n }\n\n const token = tokens.get(target)\n if (!token) {\n throw new Error(`bezel: unresolved token reference \"{${target}}\".`)\n }\n\n seen.add(target)\n const value2 = resolveValue(token.value, seen)\n seen.delete(target)\n resolved.set(target, value2)\n return value2\n }\n\n for (const token of tokens.values()) {\n token.value = resolveValue(token.value, new Set())\n }\n return tokens\n}\n","import type { ResolvedCssOptions } from \"./options\"\nimport type {\n ColorValue,\n DimensionValue,\n TokenValue,\n} from \"./types\"\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v)\n}\n\nfunction isColor(v: unknown): v is ColorValue {\n return isObject(v) && \"colorSpace\" in v && Array.isArray(v[\"components\"])\n}\n\nfunction isDimension(v: unknown): v is DimensionValue {\n return isObject(v) && typeof v[\"value\"] === \"number\" && \"unit\" in v\n}\n\n/** Round to at most `dp` decimals without trailing zeros. */\nfunction round(n: number, dp: number): number {\n const f = 10 ** dp\n return Math.round(n * f) / f\n}\n\nfunction serializeColor(color: ColorValue, format: ResolvedCssOptions[\"colorFormat\"]): string {\n if (format === \"hex\" && color.hex) return color.hex.toLowerCase()\n\n if (color.colorSpace === \"oklch\") {\n const [l = 0, c = 0, h = 0] = color.components\n const base = `oklch(${round(l, 4)} ${round(c, 4)} ${round(h, 3)})`\n if (color.alpha !== undefined && color.alpha < 1) {\n return `oklch(${round(l, 4)} ${round(c, 4)} ${round(h, 3)} / ${round(color.alpha, 4)})`\n }\n return base\n }\n\n // Unknown color space: prefer hex fallback, else CSS color() function.\n if (color.hex) return color.hex.toLowerCase()\n return `color(${color.colorSpace} ${color.components.map((n) => round(n, 4)).join(\" \")})`\n}\n\nfunction serializeDimension(dim: DimensionValue, unit: ResolvedCssOptions[\"dimensionUnit\"]): string {\n if (unit === \"rem\" && dim.unit === \"px\") {\n return `${round(dim.value / 16, 4)}rem`\n }\n return `${dim.value}${dim.unit}`\n}\n\n/** Quote a font-family name if it contains whitespace and isn't already quoted. */\nfunction quoteFamily(name: string): string {\n const trimmed = name.trim()\n if (/^['\"].*['\"]$/.test(trimmed)) return trimmed\n return /\\s/.test(trimmed) ? `\"${trimmed}\"` : trimmed\n}\n\n/** Serialize a resolved token value to a CSS declaration value. */\nexport function serializeValue(value: TokenValue, options: ResolvedCssOptions): string {\n if (isColor(value)) return serializeColor(value, options.colorFormat)\n if (isDimension(value)) return serializeDimension(value, options.dimensionUnit)\n\n // fontFamily as an array of names.\n if (Array.isArray(value)) {\n return value.map((v) => quoteFamily(String(v))).join(\", \")\n }\n\n if (typeof value === \"number\") return String(value)\n\n // Strings: could be a single font-family name or an already-formatted value.\n // Quote multi-word family names; leave comma-lists and plain values untouched.\n const str = String(value)\n if (/\\s/.test(str) && !str.includes(\",\") && !/[()]/.test(str)) {\n return quoteFamily(str)\n }\n return str\n}\n","import { flattenForContext } from \"./collapse\"\nimport { cssNames, usesExportNames } from \"./name\"\nimport { resolveReferences } from \"./resolve\"\nimport { serializeValue } from \"./serialize\"\nimport type { ResolvedCssOptions } from \"./options\"\nimport type { DtcgNode } from \"./types\"\n\n/** An ordered map of CSS variable name → serialized value for one context. */\ntype VarMap = Map<string, string>\n\n/** Build the `name → cssValue` map for a single context. */\nfunction buildContextVars(\n tokens: DtcgNode,\n context: string,\n useExportName: boolean,\n options: ResolvedCssOptions,\n): VarMap {\n const flat = resolveReferences(flattenForContext(tokens, context))\n const vars: VarMap = new Map()\n for (const token of flat.values()) {\n const names = cssNames(token, options.nameExtension, useExportName)\n if (names.length === 0) continue\n const value = serializeValue(token.value, options)\n for (const name of names) vars.set(name, value)\n }\n return vars\n}\n\nfunction renderBlock(selector: string, vars: Iterable<[string, string]>): string {\n const lines = [...vars].map(([name, value]) => ` --${name}: ${value};`)\n if (lines.length === 0) return \"\"\n return `${selector} {\\n${lines.join(\"\\n\")}\\n}`\n}\n\n/**\n * Convert a DTCG token tree into a scoped CSS string. The first context in\n * `options.contexts` is the base (emitted in full); every other context emits\n * only the variables whose value differs from the base.\n */\nexport function emitCss(tokens: DtcgNode, options: ResolvedCssOptions): string {\n const contextNames = Object.keys(options.contexts)\n const useExportName = usesExportNames(\n flattenForContext(tokens, contextNames[0]!).values(),\n options.nameExtension,\n )\n\n const [baseContext, ...overrideContexts] = contextNames\n const baseVars = buildContextVars(tokens, baseContext!, useExportName, options)\n\n const blocks: string[] = [renderBlock(options.contexts[baseContext!]!, baseVars)]\n\n for (const context of overrideContexts) {\n const vars = buildContextVars(tokens, context, useExportName, options)\n const overrides = [...vars].filter(([name, value]) => baseVars.get(name) !== value)\n const block = renderBlock(options.contexts[context]!, overrides)\n if (block) blocks.push(block)\n }\n\n const header =\n \"/* Generated by bezel — do not edit by hand. */\\n\" +\n \"/* Run `npm run tokens` (or `bezel build`) to regenerate. */\\n\"\n return `${header}\\n${blocks.filter(Boolean).join(\"\\n\\n\")}\\n`\n}\n","/**\n * Pure default constants shared by the isomorphic core and the Node layer.\n * Kept free of `node:*` imports so the browser/edge entry can use them.\n */\n\n/** Default context → selector mapping. The first key is the base context. */\nexport const DEFAULT_CONTEXTS: Record<string, string> = {\n $root: \":root\",\n dark: \".dark\",\n light: \".light\",\n}\n\n/**\n * The DTCG input file the CLI reads from the project root. This is a cross-system\n * contract: it MUST stay in sync with the platform's `TOKENS_FILE_NAME` constant\n * (gundam: libs/keypuncher/data/constants/src/lib/tokens-file.ts) so any repo/app\n * the platform connects to resolves its tokens at the same name + location.\n */\nexport const DEFAULT_INPUT = \"design-tokens.json\"\nexport const DEFAULT_VARIABLES_OUTPUT = \"variables.css\"\nexport const DEFAULT_NAME_EXTENSION = \"com.tokendesigner.app\"\n","import { DEFAULT_CONTEXTS, DEFAULT_NAME_EXTENSION } from \"./defaults\"\n\n/**\n * Options for the pure CSS transform ({@link tokensToCss}/{@link emitCss}),\n * decoupled from any filesystem concern so they work in any environment.\n * All optional; defaults make the zero-config case work.\n */\nexport interface CssOptions {\n /**\n * Map of context name → CSS selector. The first entry is the base context (full\n * output); every other context emits only the variables that differ from the base.\n * Default: `{ \"$root\": \":root\", \"dark\": \".dark\", \"light\": \".light\" }`.\n */\n contexts?: Record<string, string>\n /** Color serialization. Default: `\"oklch\"`. */\n colorFormat?: \"oklch\" | \"hex\"\n /** Dimension handling: keep the authored unit, or convert `px` → `rem`. Default: `\"preserve\"`. */\n dimensionUnit?: \"preserve\" | \"rem\"\n /** `$extensions` key holding the `exportName` array. Default: `\"com.tokendesigner.app\"`. */\n nameExtension?: string\n}\n\n/** Fully-resolved CSS-transform options (no `undefined`). */\nexport interface ResolvedCssOptions {\n contexts: Record<string, string>\n colorFormat: \"oklch\" | \"hex\"\n dimensionUnit: \"preserve\" | \"rem\"\n nameExtension: string\n}\n\n/** Apply defaults to {@link CssOptions}. Pure — no path resolution, no `node:*`. */\nexport function resolveCssOptions(options: CssOptions = {}): ResolvedCssOptions {\n const contexts = options.contexts ?? DEFAULT_CONTEXTS\n if (Object.keys(contexts).length === 0) {\n throw new Error(\"bezel: `contexts` must define at least one context.\")\n }\n\n return {\n contexts,\n colorFormat: options.colorFormat ?? \"oklch\",\n dimensionUnit: options.dimensionUnit ?? \"preserve\",\n nameExtension: options.nameExtension ?? DEFAULT_NAME_EXTENSION,\n }\n}\n","import { ROOT_CONTEXT } from \"./collapse\"\nimport type { DtcgNode } from \"./types\"\n\n/** Name the `$root` context maps to in generated output (matches the `:root` CSS scope). */\nexport const DEFAULT_CONTEXT_NAME = \"default\"\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v)\n}\n\nfunction isContextWrapper(v: unknown): boolean {\n return isObject(v) && \"$value\" in v\n}\n\n/**\n * Extract the distinct context names declared anywhere in a DTCG token tree.\n *\n * Walks to each logical token (a node with a `$root` context wrapper) and collects the\n * context keys it declares (`$root`, `dark`, `light`, …). `$root` is mapped to\n * `\"default\"` and placed first; the rest follow in first-seen order, deduped.\n */\nexport function getContexts(tokens: DtcgNode, rootName: string = DEFAULT_CONTEXT_NAME): string[] {\n const order: string[] = []\n const seen = new Set<string>()\n\n const walk = (node: DtcgNode): void => {\n if (ROOT_CONTEXT in node && isContextWrapper(node[ROOT_CONTEXT])) {\n for (const key of Object.keys(node)) {\n if (key.startsWith(\"$\") && key !== ROOT_CONTEXT) continue\n if (isContextWrapper(node[key]) && !seen.has(key)) {\n seen.add(key)\n order.push(key)\n }\n }\n return\n }\n for (const key of Object.keys(node)) {\n if (key.startsWith(\"$\")) continue\n const child = node[key]\n if (isObject(child)) walk(child as DtcgNode)\n }\n }\n\n walk(tokens)\n\n const mapped = order.map((k) => (k === ROOT_CONTEXT ? rootName : k))\n return [...new Set([rootName, ...mapped])]\n}\n\n/** Render the generated `contexts.ts` module emitted alongside `variables.css`. */\nexport function formatContextsModule(contexts: string[]): string {\n const list = contexts.map((c) => JSON.stringify(c)).join(\", \")\n return (\n \"/* Generated by bezel — do not edit by hand. */\\n\" +\n \"/* Run `npm run tokens` (or `bezel build`) to regenerate. */\\n\\n\" +\n `export const CONTEXTS = [${list}] as const\\n\\n` +\n \"export type Context = (typeof CONTEXTS)[number]\\n\"\n )\n}\n","import { flattenForContext, ROOT_CONTEXT } from \"./collapse\"\nimport { resolveReferences } from \"./resolve\"\nimport type { DtcgNode, TokenValue } from \"./types\"\n\n/** A web font to load: a family name and the weights it is used at. */\nexport interface FontDef {\n family: string\n weights: number[]\n}\n\n/** Generic CSS family keywords that are never loaded as web fonts. */\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"fangsong\",\n \"inherit\",\n \"initial\",\n \"unset\",\n])\n\nconst DEFAULT_WEIGHT = 400\n\n/** Resolve a fontFamily token value to a primary family name (first non-generic), or null. */\nfunction primaryFamily(value: TokenValue): string | null {\n const candidates = Array.isArray(value) ? value : [value]\n for (const candidate of candidates) {\n if (typeof candidate !== \"string\") continue\n const name = candidate.trim().replace(/^['\"]|['\"]$/g, \"\")\n if (name && !GENERIC_FAMILIES.has(name.toLowerCase())) return name\n }\n return null\n}\n\nfunction parentPath(path: string): string {\n const i = path.lastIndexOf(\".\")\n return i === -1 ? \"\" : path.slice(0, i)\n}\n\n/**\n * Extract the web fonts referenced by a DTCG token tree.\n *\n * Collects every distinct `fontFamily` value (references resolved), then derives each\n * family's weights from the semantic typography composites — a group whose `font-family`\n * resolves to that family contributes its sibling `font-weight`. Families used without an\n * accompanying weight default to `[400]`. Result is sorted by family for determinism.\n */\nexport function getFonts(tokens: DtcgNode): FontDef[] {\n const flat = resolveReferences(flattenForContext(tokens, ROOT_CONTEXT))\n\n const families = new Set<string>()\n const familyByParent = new Map<string, string>()\n const weightByParent = new Map<string, number>()\n\n for (const token of flat.values()) {\n if (token.type === \"fontFamily\") {\n const family = primaryFamily(token.value)\n if (family) {\n families.add(family)\n familyByParent.set(parentPath(token.path), family)\n }\n } else if (token.type === \"fontWeight\" && typeof token.value === \"number\") {\n weightByParent.set(parentPath(token.path), token.value)\n }\n }\n\n const weightsByFamily = new Map<string, Set<number>>()\n for (const [parent, family] of familyByParent) {\n const weight = weightByParent.get(parent)\n if (weight === undefined) continue\n const set = weightsByFamily.get(family) ?? new Set<number>()\n set.add(weight)\n weightsByFamily.set(family, set)\n }\n\n return [...families].sort().map((family) => {\n const weights = weightsByFamily.get(family)\n return {\n family,\n weights: weights ? [...weights].sort((a, b) => a - b) : [DEFAULT_WEIGHT],\n }\n })\n}\n\n/** Render the generated `fonts.ts` module emitted alongside `variables.css`. */\nexport function formatFontsModule(fonts: FontDef[]): string {\n const entries = fonts\n .map((f) => ` { family: ${JSON.stringify(f.family)}, weights: [${f.weights.join(\", \")}] },`)\n .join(\"\\n\")\n return (\n \"/* Generated by bezel — do not edit by hand. */\\n\" +\n \"/* Run `npm run tokens` (or `bezel build`) to regenerate. */\\n\\n\" +\n `export const FONTS = [\\n${entries}\\n] as const\\n\\n` +\n \"export type FontDef = { family: string; weights: number[] }\\n\"\n )\n}\n"],"mappings":"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","names":["isObject","isObject","isContextWrapper"]}
|