@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/LICENSE
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# PolyForm Shield License 1.0.0
|
|
2
|
+
|
|
3
|
+
Licensor: Bezel
|
|
4
|
+
|
|
5
|
+
Required Notice: Copyright © 2026 Bezel (https://bezel.new)
|
|
6
|
+
|
|
7
|
+
<https://polyformproject.org/licenses/shield/1.0.0>
|
|
8
|
+
|
|
9
|
+
## Acceptance
|
|
10
|
+
|
|
11
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
12
|
+
|
|
13
|
+
## Copyright License
|
|
14
|
+
|
|
15
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
|
|
16
|
+
|
|
17
|
+
## Distribution License
|
|
18
|
+
|
|
19
|
+
The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
|
|
20
|
+
|
|
21
|
+
## Notices
|
|
22
|
+
|
|
23
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
|
|
24
|
+
|
|
25
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
26
|
+
|
|
27
|
+
## Changes and New Works License
|
|
28
|
+
|
|
29
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
30
|
+
|
|
31
|
+
## Patent License
|
|
32
|
+
|
|
33
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
34
|
+
|
|
35
|
+
## Noncompete
|
|
36
|
+
|
|
37
|
+
Any purpose is a permitted purpose, except for providing any product that competes with the software or any product the licensor or any of its affiliates provides using the software.
|
|
38
|
+
|
|
39
|
+
## Competition
|
|
40
|
+
|
|
41
|
+
Goods and services compete even when they provide functionality through different kinds of interfaces or for different technical platforms. Applications can compete with services, libraries with plugins, frameworks with development tools, and so on, even if they're written in different programming languages or for different computer architectures. Goods and services compete even when provided free of charge. If you market a product as a practical substitute for the software or another product, it definitely competes.
|
|
42
|
+
|
|
43
|
+
## New Products
|
|
44
|
+
|
|
45
|
+
If you are using the software to provide a product that does not compete, but the licensor or any of its affiliates brings your product into competition by providing a new version of the software or another product using the software, you may continue using versions of the software available under these terms beforehand to provide your competing product, but not any later versions.
|
|
46
|
+
|
|
47
|
+
## Discontinued Products
|
|
48
|
+
|
|
49
|
+
You may begin using the software to compete with a product or service that the licensor or any of its affiliates has stopped providing, unless the licensor includes a plain-text line beginning with `Licensor Line of Business:` with the software that mentions that line of business. For example:
|
|
50
|
+
|
|
51
|
+
> Licensor Line of Business: YoyodyneCMS Content Management System (http://example.com/cms)
|
|
52
|
+
|
|
53
|
+
## Sales of Business
|
|
54
|
+
|
|
55
|
+
If the licensor or any of its affiliates sells a line of business developing the software or using the software to provide a product, the buyer can also enforce [Noncompete](#noncompete) for that product.
|
|
56
|
+
|
|
57
|
+
## Fair Use
|
|
58
|
+
|
|
59
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
60
|
+
|
|
61
|
+
## No Other Rights
|
|
62
|
+
|
|
63
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
64
|
+
|
|
65
|
+
## Patent Defense
|
|
66
|
+
|
|
67
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
68
|
+
|
|
69
|
+
## Violations
|
|
70
|
+
|
|
71
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
72
|
+
|
|
73
|
+
## No Liability
|
|
74
|
+
|
|
75
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
76
|
+
|
|
77
|
+
## Definitions
|
|
78
|
+
|
|
79
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
80
|
+
|
|
81
|
+
A **product** can be a good or service, or a combination of them.
|
|
82
|
+
|
|
83
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
84
|
+
|
|
85
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all its affiliates.
|
|
86
|
+
|
|
87
|
+
**Affiliates** means the other organizations than an organization has control over, is under the control of, or is under common control with.
|
|
88
|
+
|
|
89
|
+
**Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
90
|
+
|
|
91
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
92
|
+
|
|
93
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @bezel-labs/bezel-kit
|
|
2
|
+
|
|
3
|
+
Convert a [W3C Design Tokens (DTCG)](https://tr.designtokens.org/) file into a scoped
|
|
4
|
+
`variables.css` — one CSS scope per context (e.g. `:root`, `.dark`, `.light`). Token
|
|
5
|
+
references are resolved to literal values, and every non-base context is emitted as an
|
|
6
|
+
override-only block.
|
|
7
|
+
|
|
8
|
+
The core is isomorphic (browser / edge / Node) and imports no `node:*`. An optional Node
|
|
9
|
+
entry and a `bezel` CLI add file-system conveniences for build-time generation.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install @bezel-labs/bezel-kit
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Core — `tokensToCss` (isomorphic, no file system)
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { tokensToCss, type DtcgNode } from "@bezel-labs/bezel-kit"
|
|
23
|
+
|
|
24
|
+
const css: string = tokensToCss(tokens)
|
|
25
|
+
const hexCss = tokensToCss(tokens, { colorFormat: "hex" })
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Node — `generateVariablesCss` (reads/writes files)
|
|
29
|
+
|
|
30
|
+
The tokens file is always read from `design-tokens.json` at the project root — its name and
|
|
31
|
+
location are fixed and not configurable.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { generateVariablesCss } from "@bezel-labs/bezel-kit/node"
|
|
35
|
+
|
|
36
|
+
// reads ./design-tokens.json, writes ./variables.css
|
|
37
|
+
await generateVariablesCss()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### CLI
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
bezel build [options]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Auto-loads a `bezel.json` config from the working directory when present. Run
|
|
47
|
+
`bezel --help` for all options.
|
|
48
|
+
|
|
49
|
+
## API
|
|
50
|
+
|
|
51
|
+
- **Core (`.`):** `tokensToCss`, `emitCss`, `resolveCssOptions`, `getContexts`,
|
|
52
|
+
`formatContextsModule`, `getFonts`, `formatFontsModule`, the `DEFAULT_CONTEXTS` /
|
|
53
|
+
`DEFAULT_NAME_EXTENSION` defaults, plus the related types.
|
|
54
|
+
- **Node (`./node`):** everything above, plus `generateVariablesCss` and `resolveOptions`.
|
|
55
|
+
|
|
56
|
+
## Development
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install # install deps
|
|
60
|
+
npm run build # bundle ESM + CJS + types (index, node, cli) with tsup
|
|
61
|
+
npm test # run the Jest test suite
|
|
62
|
+
npm run typecheck
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
[PolyForm Shield 1.0.0](./LICENSE) — free to use, modify, and redistribute for any purpose
|
|
68
|
+
**except** building or providing a product that competes with [Bezel](https://bezel.new).
|
|
69
|
+
Open-source, internal, and commercial use are all permitted within that bound.
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
// src/collapse.ts
|
|
2
|
+
var ROOT_CONTEXT = "$root";
|
|
3
|
+
function isObject(v) {
|
|
4
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
5
|
+
}
|
|
6
|
+
function isContextWrapper(v) {
|
|
7
|
+
return isObject(v) && "$value" in v;
|
|
8
|
+
}
|
|
9
|
+
function isMetaKey(key) {
|
|
10
|
+
return key === "$type" || key === "$description" || key === "$extensions" || key === "$value";
|
|
11
|
+
}
|
|
12
|
+
function flattenForContext(tokens, context) {
|
|
13
|
+
const out = /* @__PURE__ */ new Map();
|
|
14
|
+
const walk = (node, path, inheritedType) => {
|
|
15
|
+
const type = typeof node.$type === "string" ? node.$type : inheritedType;
|
|
16
|
+
if ("$value" in node) {
|
|
17
|
+
out.set(path, {
|
|
18
|
+
path,
|
|
19
|
+
value: node.$value,
|
|
20
|
+
type,
|
|
21
|
+
extensions: node.$extensions
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const wrapperKeys = Object.keys(node).filter((k) => !isMetaKey(k) && isContextWrapper(node[k]));
|
|
26
|
+
if (wrapperKeys.length > 0) {
|
|
27
|
+
const chosen = node[context] ?? node[ROOT_CONTEXT] ?? node[wrapperKeys[0]];
|
|
28
|
+
out.set(path, {
|
|
29
|
+
path,
|
|
30
|
+
value: chosen.$value,
|
|
31
|
+
type,
|
|
32
|
+
extensions: node.$extensions
|
|
33
|
+
});
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
for (const key of Object.keys(node)) {
|
|
37
|
+
if (isMetaKey(key)) continue;
|
|
38
|
+
const child = node[key];
|
|
39
|
+
if (isObject(child)) {
|
|
40
|
+
walk(child, path ? `${path}.${key}` : key, type);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
walk(tokens, "", void 0);
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/name.ts
|
|
49
|
+
var DROPPED_PREFIXES = /* @__PURE__ */ new Set(["base", "semantic"]);
|
|
50
|
+
var DROPPED_SUFFIXES = /* @__PURE__ */ new Set(["default", "$root"]);
|
|
51
|
+
function exportNames(token, nameExtension) {
|
|
52
|
+
const ext = token.extensions?.[nameExtension];
|
|
53
|
+
if (ext && typeof ext === "object" && "exportName" in ext) {
|
|
54
|
+
const names = ext.exportName;
|
|
55
|
+
if (Array.isArray(names)) return names.filter((n) => typeof n === "string");
|
|
56
|
+
}
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
function usesExportNames(tokens, nameExtension) {
|
|
60
|
+
for (const token of tokens) {
|
|
61
|
+
if (exportNames(token, nameExtension) !== void 0) return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
function nameFromPath(path) {
|
|
66
|
+
const segments = path.split(".");
|
|
67
|
+
while (segments.length > 1 && DROPPED_PREFIXES.has(segments[0])) segments.shift();
|
|
68
|
+
while (segments.length > 1 && DROPPED_SUFFIXES.has(segments[segments.length - 1])) {
|
|
69
|
+
segments.pop();
|
|
70
|
+
}
|
|
71
|
+
return segments.join("-");
|
|
72
|
+
}
|
|
73
|
+
function cssNames(token, nameExtension, useExportName) {
|
|
74
|
+
if (useExportName) {
|
|
75
|
+
const names = exportNames(token, nameExtension);
|
|
76
|
+
if (!names) return [];
|
|
77
|
+
return names.filter((n) => n.length > 0);
|
|
78
|
+
}
|
|
79
|
+
return [nameFromPath(token.path)];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/resolve.ts
|
|
83
|
+
var REFERENCE_RE = /^\{([^{}]+)\}$/;
|
|
84
|
+
function aliasTarget(value) {
|
|
85
|
+
if (typeof value !== "string") return null;
|
|
86
|
+
const match = REFERENCE_RE.exec(value.trim());
|
|
87
|
+
return match ? match[1].trim() : null;
|
|
88
|
+
}
|
|
89
|
+
function resolveReferences(tokens) {
|
|
90
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
91
|
+
const resolveValue = (value, seen) => {
|
|
92
|
+
const target = aliasTarget(value);
|
|
93
|
+
if (target === null) return value;
|
|
94
|
+
if (resolved.has(target)) return resolved.get(target);
|
|
95
|
+
if (seen.has(target)) {
|
|
96
|
+
throw new Error(`bezel: circular token reference detected at "{${target}}".`);
|
|
97
|
+
}
|
|
98
|
+
const token = tokens.get(target);
|
|
99
|
+
if (!token) {
|
|
100
|
+
throw new Error(`bezel: unresolved token reference "{${target}}".`);
|
|
101
|
+
}
|
|
102
|
+
seen.add(target);
|
|
103
|
+
const value2 = resolveValue(token.value, seen);
|
|
104
|
+
seen.delete(target);
|
|
105
|
+
resolved.set(target, value2);
|
|
106
|
+
return value2;
|
|
107
|
+
};
|
|
108
|
+
for (const token of tokens.values()) {
|
|
109
|
+
token.value = resolveValue(token.value, /* @__PURE__ */ new Set());
|
|
110
|
+
}
|
|
111
|
+
return tokens;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/serialize.ts
|
|
115
|
+
function isObject2(v) {
|
|
116
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
117
|
+
}
|
|
118
|
+
function isColor(v) {
|
|
119
|
+
return isObject2(v) && "colorSpace" in v && Array.isArray(v["components"]);
|
|
120
|
+
}
|
|
121
|
+
function isDimension(v) {
|
|
122
|
+
return isObject2(v) && typeof v["value"] === "number" && "unit" in v;
|
|
123
|
+
}
|
|
124
|
+
function round(n, dp) {
|
|
125
|
+
const f = 10 ** dp;
|
|
126
|
+
return Math.round(n * f) / f;
|
|
127
|
+
}
|
|
128
|
+
function serializeColor(color, format) {
|
|
129
|
+
if (format === "hex" && color.hex) return color.hex.toLowerCase();
|
|
130
|
+
if (color.colorSpace === "oklch") {
|
|
131
|
+
const [l = 0, c = 0, h = 0] = color.components;
|
|
132
|
+
const base = `oklch(${round(l, 4)} ${round(c, 4)} ${round(h, 3)})`;
|
|
133
|
+
if (color.alpha !== void 0 && color.alpha < 1) {
|
|
134
|
+
return `oklch(${round(l, 4)} ${round(c, 4)} ${round(h, 3)} / ${round(color.alpha, 4)})`;
|
|
135
|
+
}
|
|
136
|
+
return base;
|
|
137
|
+
}
|
|
138
|
+
if (color.hex) return color.hex.toLowerCase();
|
|
139
|
+
return `color(${color.colorSpace} ${color.components.map((n) => round(n, 4)).join(" ")})`;
|
|
140
|
+
}
|
|
141
|
+
function serializeDimension(dim, unit) {
|
|
142
|
+
if (unit === "rem" && dim.unit === "px") {
|
|
143
|
+
return `${round(dim.value / 16, 4)}rem`;
|
|
144
|
+
}
|
|
145
|
+
return `${dim.value}${dim.unit}`;
|
|
146
|
+
}
|
|
147
|
+
function quoteFamily(name) {
|
|
148
|
+
const trimmed = name.trim();
|
|
149
|
+
if (/^['"].*['"]$/.test(trimmed)) return trimmed;
|
|
150
|
+
return /\s/.test(trimmed) ? `"${trimmed}"` : trimmed;
|
|
151
|
+
}
|
|
152
|
+
function serializeValue(value, options) {
|
|
153
|
+
if (isColor(value)) return serializeColor(value, options.colorFormat);
|
|
154
|
+
if (isDimension(value)) return serializeDimension(value, options.dimensionUnit);
|
|
155
|
+
if (Array.isArray(value)) {
|
|
156
|
+
return value.map((v) => quoteFamily(String(v))).join(", ");
|
|
157
|
+
}
|
|
158
|
+
if (typeof value === "number") return String(value);
|
|
159
|
+
const str = String(value);
|
|
160
|
+
if (/\s/.test(str) && !str.includes(",") && !/[()]/.test(str)) {
|
|
161
|
+
return quoteFamily(str);
|
|
162
|
+
}
|
|
163
|
+
return str;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/emit.ts
|
|
167
|
+
function buildContextVars(tokens, context, useExportName, options) {
|
|
168
|
+
const flat = resolveReferences(flattenForContext(tokens, context));
|
|
169
|
+
const vars = /* @__PURE__ */ new Map();
|
|
170
|
+
for (const token of flat.values()) {
|
|
171
|
+
const names = cssNames(token, options.nameExtension, useExportName);
|
|
172
|
+
if (names.length === 0) continue;
|
|
173
|
+
const value = serializeValue(token.value, options);
|
|
174
|
+
for (const name of names) vars.set(name, value);
|
|
175
|
+
}
|
|
176
|
+
return vars;
|
|
177
|
+
}
|
|
178
|
+
function renderBlock(selector, vars) {
|
|
179
|
+
const lines = [...vars].map(([name, value]) => ` --${name}: ${value};`);
|
|
180
|
+
if (lines.length === 0) return "";
|
|
181
|
+
return `${selector} {
|
|
182
|
+
${lines.join("\n")}
|
|
183
|
+
}`;
|
|
184
|
+
}
|
|
185
|
+
function emitCss(tokens, options) {
|
|
186
|
+
const contextNames = Object.keys(options.contexts);
|
|
187
|
+
const useExportName = usesExportNames(
|
|
188
|
+
flattenForContext(tokens, contextNames[0]).values(),
|
|
189
|
+
options.nameExtension
|
|
190
|
+
);
|
|
191
|
+
const [baseContext, ...overrideContexts] = contextNames;
|
|
192
|
+
const baseVars = buildContextVars(tokens, baseContext, useExportName, options);
|
|
193
|
+
const blocks = [renderBlock(options.contexts[baseContext], baseVars)];
|
|
194
|
+
for (const context of overrideContexts) {
|
|
195
|
+
const vars = buildContextVars(tokens, context, useExportName, options);
|
|
196
|
+
const overrides = [...vars].filter(([name, value]) => baseVars.get(name) !== value);
|
|
197
|
+
const block = renderBlock(options.contexts[context], overrides);
|
|
198
|
+
if (block) blocks.push(block);
|
|
199
|
+
}
|
|
200
|
+
const header = "/* Generated by bezel \u2014 do not edit by hand. */\n/* Run `npm run tokens` (or `bezel build`) to regenerate. */\n";
|
|
201
|
+
return `${header}
|
|
202
|
+
${blocks.filter(Boolean).join("\n\n")}
|
|
203
|
+
`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// src/defaults.ts
|
|
207
|
+
var DEFAULT_CONTEXTS = {
|
|
208
|
+
$root: ":root",
|
|
209
|
+
dark: ".dark",
|
|
210
|
+
light: ".light"
|
|
211
|
+
};
|
|
212
|
+
var DEFAULT_INPUT = "design-tokens.json";
|
|
213
|
+
var DEFAULT_VARIABLES_OUTPUT = "variables.css";
|
|
214
|
+
var DEFAULT_NAME_EXTENSION = "com.tokendesigner.app";
|
|
215
|
+
|
|
216
|
+
// src/options.ts
|
|
217
|
+
function resolveCssOptions(options = {}) {
|
|
218
|
+
const contexts = options.contexts ?? DEFAULT_CONTEXTS;
|
|
219
|
+
if (Object.keys(contexts).length === 0) {
|
|
220
|
+
throw new Error("bezel: `contexts` must define at least one context.");
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
contexts,
|
|
224
|
+
colorFormat: options.colorFormat ?? "oklch",
|
|
225
|
+
dimensionUnit: options.dimensionUnit ?? "preserve",
|
|
226
|
+
nameExtension: options.nameExtension ?? DEFAULT_NAME_EXTENSION
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/contexts.ts
|
|
231
|
+
var DEFAULT_CONTEXT_NAME = "default";
|
|
232
|
+
function isObject3(v) {
|
|
233
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
234
|
+
}
|
|
235
|
+
function isContextWrapper2(v) {
|
|
236
|
+
return isObject3(v) && "$value" in v;
|
|
237
|
+
}
|
|
238
|
+
function getContexts(tokens, rootName = DEFAULT_CONTEXT_NAME) {
|
|
239
|
+
const order = [];
|
|
240
|
+
const seen = /* @__PURE__ */ new Set();
|
|
241
|
+
const walk = (node) => {
|
|
242
|
+
if (ROOT_CONTEXT in node && isContextWrapper2(node[ROOT_CONTEXT])) {
|
|
243
|
+
for (const key of Object.keys(node)) {
|
|
244
|
+
if (key.startsWith("$") && key !== ROOT_CONTEXT) continue;
|
|
245
|
+
if (isContextWrapper2(node[key]) && !seen.has(key)) {
|
|
246
|
+
seen.add(key);
|
|
247
|
+
order.push(key);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
for (const key of Object.keys(node)) {
|
|
253
|
+
if (key.startsWith("$")) continue;
|
|
254
|
+
const child = node[key];
|
|
255
|
+
if (isObject3(child)) walk(child);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
walk(tokens);
|
|
259
|
+
const mapped = order.map((k) => k === ROOT_CONTEXT ? rootName : k);
|
|
260
|
+
return [.../* @__PURE__ */ new Set([rootName, ...mapped])];
|
|
261
|
+
}
|
|
262
|
+
function formatContextsModule(contexts) {
|
|
263
|
+
const list = contexts.map((c) => JSON.stringify(c)).join(", ");
|
|
264
|
+
return `/* Generated by bezel \u2014 do not edit by hand. */
|
|
265
|
+
/* Run \`npm run tokens\` (or \`bezel build\`) to regenerate. */
|
|
266
|
+
|
|
267
|
+
export const CONTEXTS = [${list}] as const
|
|
268
|
+
|
|
269
|
+
export type Context = (typeof CONTEXTS)[number]
|
|
270
|
+
`;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/fonts.ts
|
|
274
|
+
var GENERIC_FAMILIES = /* @__PURE__ */ new Set([
|
|
275
|
+
"serif",
|
|
276
|
+
"sans-serif",
|
|
277
|
+
"monospace",
|
|
278
|
+
"cursive",
|
|
279
|
+
"fantasy",
|
|
280
|
+
"system-ui",
|
|
281
|
+
"ui-serif",
|
|
282
|
+
"ui-sans-serif",
|
|
283
|
+
"ui-monospace",
|
|
284
|
+
"ui-rounded",
|
|
285
|
+
"math",
|
|
286
|
+
"emoji",
|
|
287
|
+
"fangsong",
|
|
288
|
+
"inherit",
|
|
289
|
+
"initial",
|
|
290
|
+
"unset"
|
|
291
|
+
]);
|
|
292
|
+
var DEFAULT_WEIGHT = 400;
|
|
293
|
+
function primaryFamily(value) {
|
|
294
|
+
const candidates = Array.isArray(value) ? value : [value];
|
|
295
|
+
for (const candidate of candidates) {
|
|
296
|
+
if (typeof candidate !== "string") continue;
|
|
297
|
+
const name = candidate.trim().replace(/^['"]|['"]$/g, "");
|
|
298
|
+
if (name && !GENERIC_FAMILIES.has(name.toLowerCase())) return name;
|
|
299
|
+
}
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
function parentPath(path) {
|
|
303
|
+
const i = path.lastIndexOf(".");
|
|
304
|
+
return i === -1 ? "" : path.slice(0, i);
|
|
305
|
+
}
|
|
306
|
+
function getFonts(tokens) {
|
|
307
|
+
const flat = resolveReferences(flattenForContext(tokens, ROOT_CONTEXT));
|
|
308
|
+
const families = /* @__PURE__ */ new Set();
|
|
309
|
+
const familyByParent = /* @__PURE__ */ new Map();
|
|
310
|
+
const weightByParent = /* @__PURE__ */ new Map();
|
|
311
|
+
for (const token of flat.values()) {
|
|
312
|
+
if (token.type === "fontFamily") {
|
|
313
|
+
const family = primaryFamily(token.value);
|
|
314
|
+
if (family) {
|
|
315
|
+
families.add(family);
|
|
316
|
+
familyByParent.set(parentPath(token.path), family);
|
|
317
|
+
}
|
|
318
|
+
} else if (token.type === "fontWeight" && typeof token.value === "number") {
|
|
319
|
+
weightByParent.set(parentPath(token.path), token.value);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const weightsByFamily = /* @__PURE__ */ new Map();
|
|
323
|
+
for (const [parent, family] of familyByParent) {
|
|
324
|
+
const weight = weightByParent.get(parent);
|
|
325
|
+
if (weight === void 0) continue;
|
|
326
|
+
const set = weightsByFamily.get(family) ?? /* @__PURE__ */ new Set();
|
|
327
|
+
set.add(weight);
|
|
328
|
+
weightsByFamily.set(family, set);
|
|
329
|
+
}
|
|
330
|
+
return [...families].sort().map((family) => {
|
|
331
|
+
const weights = weightsByFamily.get(family);
|
|
332
|
+
return {
|
|
333
|
+
family,
|
|
334
|
+
weights: weights ? [...weights].sort((a, b) => a - b) : [DEFAULT_WEIGHT]
|
|
335
|
+
};
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
function formatFontsModule(fonts) {
|
|
339
|
+
const entries = fonts.map((f) => ` { family: ${JSON.stringify(f.family)}, weights: [${f.weights.join(", ")}] },`).join("\n");
|
|
340
|
+
return `/* Generated by bezel \u2014 do not edit by hand. */
|
|
341
|
+
/* Run \`npm run tokens\` (or \`bezel build\`) to regenerate. */
|
|
342
|
+
|
|
343
|
+
export const FONTS = [
|
|
344
|
+
${entries}
|
|
345
|
+
] as const
|
|
346
|
+
|
|
347
|
+
export type FontDef = { family: string; weights: number[] }
|
|
348
|
+
`;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// src/index.ts
|
|
352
|
+
function tokensToCss(tokens, options = {}) {
|
|
353
|
+
return emitCss(tokens, resolveCssOptions(options));
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export {
|
|
357
|
+
DEFAULT_CONTEXTS,
|
|
358
|
+
DEFAULT_INPUT,
|
|
359
|
+
DEFAULT_VARIABLES_OUTPUT,
|
|
360
|
+
DEFAULT_NAME_EXTENSION,
|
|
361
|
+
resolveCssOptions,
|
|
362
|
+
emitCss,
|
|
363
|
+
DEFAULT_CONTEXT_NAME,
|
|
364
|
+
getContexts,
|
|
365
|
+
formatContextsModule,
|
|
366
|
+
getFonts,
|
|
367
|
+
formatFontsModule,
|
|
368
|
+
tokensToCss
|
|
369
|
+
};
|
|
370
|
+
//# sourceMappingURL=chunk-5EW7EW3R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../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","../src/index.ts"],"sourcesContent":["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","/**\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"],"mappings":"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","names":["isObject","isObject","isContextWrapper"]}
|