@mp3wizard/figma-console-mcp 1.27.2 → 1.28.2
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/README.md +9 -7
- package/dist/apps/design-system-dashboard/mcp-app.html +78 -78
- package/dist/apps/token-browser/mcp-app.html +60 -59
- package/dist/cloudflare/core/tokens/alias-resolver.js +37 -0
- package/dist/cloudflare/core/tokens/formatters/json.js +185 -5
- package/dist/cloudflare/core/tokens/formatters/scss.js +251 -3
- package/dist/cloudflare/core/tokens/formatters/stubs.js +6 -4
- package/dist/cloudflare/core/tokens/formatters/style-dictionary-v3.js +206 -3
- package/dist/cloudflare/core/tokens/formatters/tailwind-v3.js +236 -3
- package/dist/cloudflare/core/tokens/formatters/tailwind-v4.js +329 -3
- package/dist/cloudflare/core/tokens/formatters/tokens-studio.js +249 -3
- package/dist/cloudflare/core/tokens/formatters/ts-module.js +197 -3
- package/dist/cloudflare/core/tokens/index.js +1 -1
- package/dist/cloudflare/core/tokens/parsers/stubs.js +13 -6
- package/dist/cloudflare/core/tokens-tools.js +12 -2
- package/dist/cloudflare/index.js +3 -3
- package/dist/core/tokens/alias-resolver.d.ts +15 -0
- package/dist/core/tokens/alias-resolver.d.ts.map +1 -1
- package/dist/core/tokens/alias-resolver.js +37 -0
- package/dist/core/tokens/alias-resolver.js.map +1 -1
- package/dist/core/tokens/formatters/json.d.ts +34 -2
- package/dist/core/tokens/formatters/json.d.ts.map +1 -1
- package/dist/core/tokens/formatters/json.js +185 -5
- package/dist/core/tokens/formatters/json.js.map +1 -1
- package/dist/core/tokens/formatters/scss.d.ts +23 -1
- package/dist/core/tokens/formatters/scss.d.ts.map +1 -1
- package/dist/core/tokens/formatters/scss.js +251 -3
- package/dist/core/tokens/formatters/scss.js.map +1 -1
- package/dist/core/tokens/formatters/stubs.d.ts +3 -3
- package/dist/core/tokens/formatters/stubs.d.ts.map +1 -1
- package/dist/core/tokens/formatters/stubs.js +6 -4
- package/dist/core/tokens/formatters/stubs.js.map +1 -1
- package/dist/core/tokens/formatters/style-dictionary-v3.d.ts +42 -1
- package/dist/core/tokens/formatters/style-dictionary-v3.d.ts.map +1 -1
- package/dist/core/tokens/formatters/style-dictionary-v3.js +206 -3
- package/dist/core/tokens/formatters/style-dictionary-v3.js.map +1 -1
- package/dist/core/tokens/formatters/tailwind-v3.d.ts +34 -1
- package/dist/core/tokens/formatters/tailwind-v3.d.ts.map +1 -1
- package/dist/core/tokens/formatters/tailwind-v3.js +236 -3
- package/dist/core/tokens/formatters/tailwind-v3.js.map +1 -1
- package/dist/core/tokens/formatters/tailwind-v4.d.ts +38 -1
- package/dist/core/tokens/formatters/tailwind-v4.d.ts.map +1 -1
- package/dist/core/tokens/formatters/tailwind-v4.js +329 -3
- package/dist/core/tokens/formatters/tailwind-v4.js.map +1 -1
- package/dist/core/tokens/formatters/tokens-studio.d.ts +41 -1
- package/dist/core/tokens/formatters/tokens-studio.d.ts.map +1 -1
- package/dist/core/tokens/formatters/tokens-studio.js +249 -3
- package/dist/core/tokens/formatters/tokens-studio.js.map +1 -1
- package/dist/core/tokens/formatters/ts-module.d.ts +32 -1
- package/dist/core/tokens/formatters/ts-module.d.ts.map +1 -1
- package/dist/core/tokens/formatters/ts-module.js +197 -3
- package/dist/core/tokens/formatters/ts-module.js.map +1 -1
- package/dist/core/tokens/index.d.ts +1 -1
- package/dist/core/tokens/index.d.ts.map +1 -1
- package/dist/core/tokens/index.js +1 -1
- package/dist/core/tokens/index.js.map +1 -1
- package/dist/core/tokens/parsers/stubs.d.ts +9 -5
- package/dist/core/tokens/parsers/stubs.d.ts.map +1 -1
- package/dist/core/tokens/parsers/stubs.js +13 -6
- package/dist/core/tokens/parsers/stubs.js.map +1 -1
- package/dist/core/tokens-tools.d.ts.map +1 -1
- package/dist/core/tokens-tools.js +12 -2
- package/dist/core/tokens-tools.js.map +1 -1
- package/figma-desktop-bridge/code.js +1 -1
- package/package.json +18 -4
|
@@ -1,4 +1,198 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript module formatter.
|
|
3
|
+
*
|
|
4
|
+
* Output shape:
|
|
5
|
+
*
|
|
6
|
+
* // tokens.ts
|
|
7
|
+
* export const tokens = {
|
|
8
|
+
* color: {
|
|
9
|
+
* primary: "#4085F2",
|
|
10
|
+
* brand: { primary: "#FF00AA" }
|
|
11
|
+
* },
|
|
12
|
+
* spacing: {
|
|
13
|
+
* md: "16px"
|
|
14
|
+
* }
|
|
15
|
+
* } as const;
|
|
16
|
+
*
|
|
17
|
+
* export type Tokens = typeof tokens;
|
|
18
|
+
*
|
|
19
|
+
* Multi-mode tokens emit as nested objects keyed by mode name:
|
|
20
|
+
*
|
|
21
|
+
* export const tokens = {
|
|
22
|
+
* mode: {
|
|
23
|
+
* primary: { Light: "#FFFFFF", Dark: "#000000" }
|
|
24
|
+
* }
|
|
25
|
+
* } as const;
|
|
26
|
+
*
|
|
27
|
+
* Aliases get resolved at write time to the literal value (TypeScript
|
|
28
|
+
* can't natively express references). Cross-library aliases get emitted
|
|
29
|
+
* as `null` with a "TODO: cross-library alias unresolved" comment so
|
|
30
|
+
* consumers see the gap.
|
|
31
|
+
*/
|
|
32
|
+
import { buildTokenIndex, resolveAliasChain } from "../alias-resolver.js";
|
|
33
|
+
export function formatTsModule(doc, opts) {
|
|
34
|
+
const warnings = [];
|
|
35
|
+
const files = [];
|
|
36
|
+
const splitByCollection = opts.target.splitByCollection ?? false;
|
|
37
|
+
// splitByMode doesn't make conceptual sense for a TypeScript module
|
|
38
|
+
// (the value is held in-memory at runtime, not selected by CSS cascade).
|
|
39
|
+
// TypeScript modules can't natively express alias references — runtime
|
|
40
|
+
// code reading tokens.color.X gets a string at runtime, no resolution
|
|
41
|
+
// logic. Build a document-wide token index so aliases resolve to their
|
|
42
|
+
// literal target at export time. The index spans every set even when
|
|
43
|
+
// splitByCollection writes single-set files, because aliases often
|
|
44
|
+
// cross set boundaries (semantic → primitives).
|
|
45
|
+
const tokenIndex = buildTokenIndex(doc);
|
|
46
|
+
if (splitByCollection) {
|
|
47
|
+
for (const set of doc.sets) {
|
|
48
|
+
files.push({
|
|
49
|
+
path: filenameFor(opts, set),
|
|
50
|
+
content: renderTsFile([set], opts, tokenIndex, warnings),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
files.push({
|
|
56
|
+
path: filenameFor(opts),
|
|
57
|
+
content: renderTsFile(doc.sets, opts, tokenIndex, warnings),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return { files, warnings };
|
|
61
|
+
}
|
|
62
|
+
function filenameFor(opts, set) {
|
|
63
|
+
if (opts.target.filename)
|
|
64
|
+
return opts.target.filename;
|
|
65
|
+
if (set)
|
|
66
|
+
return `${slugify(set.name)}.tokens.ts`;
|
|
67
|
+
return "tokens.ts";
|
|
68
|
+
}
|
|
69
|
+
function slugify(s) {
|
|
70
|
+
return s
|
|
71
|
+
.trim()
|
|
72
|
+
.toLowerCase()
|
|
73
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
74
|
+
.replace(/^-+|-+$/g, "");
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Convert a path segment to a valid JS identifier or quoted-key form.
|
|
78
|
+
* Numeric leading chars, hyphens, etc. → quoted string key.
|
|
79
|
+
*/
|
|
80
|
+
function jsKey(segment) {
|
|
81
|
+
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(segment))
|
|
82
|
+
return segment;
|
|
83
|
+
return JSON.stringify(segment);
|
|
84
|
+
}
|
|
85
|
+
function renderTsFile(sets, opts, tokenIndex, warnings) {
|
|
86
|
+
const prefix = opts.target.prefix ?? "";
|
|
87
|
+
const lines = [];
|
|
88
|
+
lines.push("/**");
|
|
89
|
+
lines.push(" * Generated by figma-console-mcp — do not edit by hand.");
|
|
90
|
+
lines.push(" * Regenerate with: figma_export_tokens (or your npm tokens:export script)");
|
|
91
|
+
lines.push(" */");
|
|
92
|
+
lines.push("");
|
|
93
|
+
const constName = prefix
|
|
94
|
+
? `${prefix.replace(/-+$/, "").replace(/-(\w)/g, (_, c) => c.toUpperCase())}Tokens`
|
|
95
|
+
: "tokens";
|
|
96
|
+
// Build the nested object structure by walking each set's tokens.
|
|
97
|
+
const tree = {};
|
|
98
|
+
for (const set of sets) {
|
|
99
|
+
for (const token of set.tokens) {
|
|
100
|
+
writeTokenIntoTree(tree, token, set, tokenIndex, warnings);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
lines.push(`export const ${constName} = ${renderTree(tree, 0)} as const;`);
|
|
104
|
+
lines.push("");
|
|
105
|
+
lines.push(`export type ${constName[0].toUpperCase()}${constName.slice(1)} = typeof ${constName};`);
|
|
106
|
+
lines.push("");
|
|
107
|
+
return lines.join("\n");
|
|
108
|
+
}
|
|
109
|
+
function writeTokenIntoTree(tree, token, set, tokenIndex, warnings) {
|
|
110
|
+
let cursor = tree;
|
|
111
|
+
for (let i = 0; i < token.path.length - 1; i++) {
|
|
112
|
+
const segment = token.path[i];
|
|
113
|
+
let next = cursor[segment];
|
|
114
|
+
if (!next || isLeaf(next)) {
|
|
115
|
+
next = {};
|
|
116
|
+
cursor[segment] = next;
|
|
117
|
+
}
|
|
118
|
+
cursor = next;
|
|
119
|
+
}
|
|
120
|
+
const leafKey = token.path[token.path.length - 1];
|
|
121
|
+
const isMulti = set.modes.length > 1;
|
|
122
|
+
const resolvedValues = {};
|
|
123
|
+
for (const [modeName, value] of Object.entries(token.values)) {
|
|
124
|
+
let effective = value;
|
|
125
|
+
if (value.reference) {
|
|
126
|
+
effective = resolveAliasChain(value, modeName, tokenIndex);
|
|
127
|
+
if (!effective) {
|
|
128
|
+
const bare = value.reference.replace(/^\{|\}$/g, "");
|
|
129
|
+
const reason = bare.startsWith("__library:") || bare === "unknown"
|
|
130
|
+
? "cross-library alias"
|
|
131
|
+
: "alias target not found";
|
|
132
|
+
warnings.push(`Skipped ${token.path.join(".")} (mode "${modeName}") in TS module — ${reason}: ${value.reference}.`);
|
|
133
|
+
resolvedValues[modeName] = null;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (!effective || effective.literal === undefined || effective.literal === null)
|
|
138
|
+
continue;
|
|
139
|
+
resolvedValues[modeName] = formatLiteral(effective.literal, token.type);
|
|
140
|
+
}
|
|
141
|
+
cursor[leafKey] = {
|
|
142
|
+
__leaf: true,
|
|
143
|
+
values: resolvedValues,
|
|
144
|
+
type: token.type,
|
|
145
|
+
isMultiMode: isMulti,
|
|
146
|
+
description: token.description,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function isLeaf(node) {
|
|
150
|
+
return node.__leaf === true;
|
|
151
|
+
}
|
|
152
|
+
function renderTree(tree, indent) {
|
|
153
|
+
const ind = " ".repeat(indent);
|
|
154
|
+
const innerInd = " ".repeat(indent + 1);
|
|
155
|
+
const entries = [];
|
|
156
|
+
for (const [key, value] of Object.entries(tree)) {
|
|
157
|
+
const k = jsKey(key);
|
|
158
|
+
if (isLeaf(value)) {
|
|
159
|
+
const leaf = value;
|
|
160
|
+
if (leaf.isMultiMode) {
|
|
161
|
+
// Emit as { Mode: value } object
|
|
162
|
+
const modeEntries = [];
|
|
163
|
+
for (const [m, v] of Object.entries(leaf.values)) {
|
|
164
|
+
modeEntries.push(`${jsKey(m)}: ${renderValue(v)}`);
|
|
165
|
+
}
|
|
166
|
+
entries.push(`${innerInd}${k}: { ${modeEntries.join(", ")} }`);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Single-mode: emit value directly
|
|
170
|
+
const onlyValue = Object.values(leaf.values)[0];
|
|
171
|
+
entries.push(`${innerInd}${k}: ${renderValue(onlyValue)}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
entries.push(`${innerInd}${k}: ${renderTree(value, indent + 1)}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (entries.length === 0)
|
|
179
|
+
return "{}";
|
|
180
|
+
return `{\n${entries.join(",\n")},\n${ind}}`;
|
|
181
|
+
}
|
|
182
|
+
function renderValue(v) {
|
|
183
|
+
if (v === null)
|
|
184
|
+
return "null /* TODO: cross-library alias unresolved */";
|
|
185
|
+
if (typeof v === "string")
|
|
186
|
+
return JSON.stringify(v);
|
|
187
|
+
if (typeof v === "number" || typeof v === "boolean")
|
|
188
|
+
return String(v);
|
|
189
|
+
return JSON.stringify(v);
|
|
190
|
+
}
|
|
191
|
+
function formatLiteral(value, type) {
|
|
192
|
+
if (typeof value === "number") {
|
|
193
|
+
if (type === "dimension")
|
|
194
|
+
return `${value}px`;
|
|
195
|
+
return value;
|
|
196
|
+
}
|
|
197
|
+
return value;
|
|
4
198
|
}
|
|
@@ -11,5 +11,5 @@ export { TokensConfigSchema, loadTokensConfig, findTokensConfig, DEFAULT_TOKENS_
|
|
|
11
11
|
export { ExportTokensInputSchema, ImportTokensInputSchema, ExportFormatSchema, ImportFormatSchema, SyncStrategySchema, ConflictResolutionSchema, } from "./schemas.js";
|
|
12
12
|
export { parse, detectFormat, } from "./parsers/index.js";
|
|
13
13
|
export { format, } from "./formatters/index.js";
|
|
14
|
-
export { buildTokenIndex, resolveReference, validateAliases, formatDtcgReference, parseDtcgReference, } from "./alias-resolver.js";
|
|
14
|
+
export { buildTokenIndex, resolveReference, resolveAliasChain, validateAliases, formatDtcgReference, parseDtcgReference, } from "./alias-resolver.js";
|
|
15
15
|
export { convertFigmaVariablesToDocument, } from "./figma-converter.js";
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared NotImplementedError for
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* Shared NotImplementedError for parser stubs.
|
|
3
|
+
*
|
|
4
|
+
* Only DTCG is implemented as a parser today — that's the canonical
|
|
5
|
+
* round-trip format for `figma_import_tokens`. Other parsers are
|
|
6
|
+
* scaffolding for potential future import-source support; the way to get
|
|
7
|
+
* tokens INTO Figma now is via DTCG JSON (you can generate that JSON from
|
|
8
|
+
* any source with your own tooling). The export side (Figma → code) is
|
|
9
|
+
* fully covered for all 10 formats — see formatters/stubs.ts for that
|
|
10
|
+
* surface.
|
|
7
11
|
*/
|
|
8
12
|
export class TokenFormatNotImplementedError extends Error {
|
|
9
13
|
constructor(formatName, kind) {
|
|
10
|
-
|
|
14
|
+
const guidance = kind === "parser"
|
|
15
|
+
? `Only the DTCG parser is implemented today. To import tokens into Figma from ${formatName}, convert to DTCG JSON first (or open an issue if you need direct ${formatName} import support).`
|
|
16
|
+
: `Implemented formatters: dtcg, css-vars, tailwind-v4, tailwind-v3, scss, ts-module, json-flat, json-nested, style-dictionary-v3, tokens-studio. If you need ${formatName}, open an issue with your use case.`;
|
|
17
|
+
super(`[figma-console-mcp] The ${formatName} ${kind} is not implemented. ${guidance}`);
|
|
11
18
|
this.name = "TokenFormatNotImplementedError";
|
|
12
19
|
}
|
|
13
20
|
}
|
|
@@ -30,10 +30,20 @@ const logger = createChildLogger({ component: "tokens-tools" });
|
|
|
30
30
|
* on every exported token document. Kept in sync with package.json by
|
|
31
31
|
* scripts/release.sh — see step 3 of the release flow.
|
|
32
32
|
*/
|
|
33
|
-
const MCP_VERSION = "1.
|
|
33
|
+
const MCP_VERSION = "1.28.1";
|
|
34
34
|
const EXPORT_TOOL_DESCRIPTION = `Export Figma variables to design token files in your codebase. Bidirectional with figma_import_tokens — together they replace Style Dictionary and Tokens Studio's export pipeline for the popular styling methods.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
FULLY-IMPLEMENTED OUTPUT FORMATS:
|
|
37
|
+
• dtcg — W3C DTCG JSON. Canonical pivot format. Round-trip safe via \`$extensions["figma-console-mcp"]\`.
|
|
38
|
+
• css-vars — CSS custom properties with mode-aware selectors (\`:root\`, \`.dark\`, \`[data-theme=...]\`).
|
|
39
|
+
• tailwind-v4 — Tailwind v4 \`@theme inline\` block. Token-to-namespace mapping (color/*, spacing/*, radius/*, etc.) generates Tailwind utility classes.
|
|
40
|
+
• tailwind-v3 — \`tailwind.config.js\` theme.extend object grouped under Tailwind's theme keys (colors, spacing, fontFamily, etc.).
|
|
41
|
+
• scss — \`$var: value;\` declarations. Multi-mode emits a primary variable + a mode-keyed SCSS map for runtime access.
|
|
42
|
+
• ts-module — \`export const tokens = { ... } as const\` with derived \`Tokens\` type. Multi-mode tokens emit as \`{ Light: ..., Dark: ... }\` objects.
|
|
43
|
+
• json-flat — flat key-value JSON (\`{"ds-color-primary": "#4085F2"}\`) for custom build scripts.
|
|
44
|
+
• json-nested — nested object JSON mirroring the token path tree.
|
|
45
|
+
• style-dictionary-v3 — SD v3 source format with bare \`value\`/\`type\` keys (back-compat for existing SD users).
|
|
46
|
+
• tokens-studio — Tokens Studio multi-file layout (\`$themes.json\` + \`$metadata.json\` + per-set files). Preserves Figma collection/mode bindings for round-trip with the TS plugin.
|
|
37
47
|
|
|
38
48
|
ZERO-ARG USAGE: With a tokens.config.json at your project root, just call the tool with no args — it picks up source dir, output formats, modes, prefix, etc. from config. See the response's \`suggestedScaffold\` payload when no config is detected — present it to the user, write the scaffold via your file tools, then call again.
|
|
39
49
|
|
package/dist/cloudflare/index.js
CHANGED
|
@@ -73,7 +73,7 @@ export class FigmaConsoleMCPv3 extends McpAgent {
|
|
|
73
73
|
this.server = (() => {
|
|
74
74
|
const s = new McpServer({
|
|
75
75
|
name: "Figma Console MCP",
|
|
76
|
-
version: "1.
|
|
76
|
+
version: "1.28.1",
|
|
77
77
|
});
|
|
78
78
|
// Identity wrap — every tool's response and thrown error gets stamped
|
|
79
79
|
// with our MCP name so cross-MCP attribution is unambiguous.
|
|
@@ -1077,7 +1077,7 @@ export default {
|
|
|
1077
1077
|
});
|
|
1078
1078
|
const statelessServer = new McpServer({
|
|
1079
1079
|
name: "Figma Console MCP",
|
|
1080
|
-
version: "1.
|
|
1080
|
+
version: "1.28.1",
|
|
1081
1081
|
});
|
|
1082
1082
|
wrapServerForIdentity(statelessServer);
|
|
1083
1083
|
// ================================================================
|
|
@@ -1712,7 +1712,7 @@ export default {
|
|
|
1712
1712
|
return new Response(JSON.stringify({
|
|
1713
1713
|
status: "healthy",
|
|
1714
1714
|
service: "Figma Console MCP",
|
|
1715
|
-
version: "1.
|
|
1715
|
+
version: "1.28.1",
|
|
1716
1716
|
endpoints: {
|
|
1717
1717
|
mcp: ["/sse", "/mcp"],
|
|
1718
1718
|
oauth_mcp_spec: ["/.well-known/oauth-authorization-server", "/authorize", "/token", "/oauth/register"],
|
|
@@ -22,6 +22,21 @@ export declare function buildTokenIndex(doc: TokenDocument): Map<string, Token>;
|
|
|
22
22
|
* throws if the reference is unresolvable or cyclic.
|
|
23
23
|
*/
|
|
24
24
|
export declare function resolveReference(reference: string, mode: string, index: Map<string, Token>, seen?: Set<string>): TokenValue;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve an alias chain to its final literal value, walking through
|
|
27
|
+
* intermediate alias hops. Returns the final TokenValue (with `literal` set
|
|
28
|
+
* if resolution succeeded) or `null` if the chain ends at a cross-library
|
|
29
|
+
* reference / unresolvable target / cycle.
|
|
30
|
+
*
|
|
31
|
+
* Used by formatters that can't natively express alias references in their
|
|
32
|
+
* output (Tailwind v3, TypeScript modules, plain JSON) — those need literal
|
|
33
|
+
* values at export time.
|
|
34
|
+
*
|
|
35
|
+
* Safer counterpart of `resolveReference` because it swallows errors
|
|
36
|
+
* (unresolvable / cycle) into `null` rather than throwing; formatters can
|
|
37
|
+
* then emit a comment or skip the token instead of failing the whole export.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveAliasChain(value: TokenValue, mode: string, index: Map<string, Token>): TokenValue | null;
|
|
25
40
|
/**
|
|
26
41
|
* Validate every alias in the document. Returns a list of error messages —
|
|
27
42
|
* empty array means all aliases resolve cleanly.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alias-resolver.d.ts","sourceRoot":"","sources":["../../../src/core/tokens/alias-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEnE;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAStE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,EACzB,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAC5B,UAAU,CAsCZ;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,EAAE,CAqB5D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAEnE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAI7D"}
|
|
1
|
+
{"version":3,"file":"alias-resolver.d.ts","sourceRoot":"","sources":["../../../src/core/tokens/alias-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEnE;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAStE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,EACzB,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAC5B,UAAU,CAsCZ;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,GACxB,UAAU,GAAG,IAAI,CAqBnB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,EAAE,CAqB5D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAEnE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAI7D"}
|
|
@@ -56,6 +56,43 @@ export function resolveReference(reference, mode, index, seen = new Set()) {
|
|
|
56
56
|
}
|
|
57
57
|
return value;
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Resolve an alias chain to its final literal value, walking through
|
|
61
|
+
* intermediate alias hops. Returns the final TokenValue (with `literal` set
|
|
62
|
+
* if resolution succeeded) or `null` if the chain ends at a cross-library
|
|
63
|
+
* reference / unresolvable target / cycle.
|
|
64
|
+
*
|
|
65
|
+
* Used by formatters that can't natively express alias references in their
|
|
66
|
+
* output (Tailwind v3, TypeScript modules, plain JSON) — those need literal
|
|
67
|
+
* values at export time.
|
|
68
|
+
*
|
|
69
|
+
* Safer counterpart of `resolveReference` because it swallows errors
|
|
70
|
+
* (unresolvable / cycle) into `null` rather than throwing; formatters can
|
|
71
|
+
* then emit a comment or skip the token instead of failing the whole export.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveAliasChain(value, mode, index) {
|
|
74
|
+
if (!value.reference)
|
|
75
|
+
return value;
|
|
76
|
+
// Cross-library aliases are not resolvable — formatters should skip with a comment.
|
|
77
|
+
const bare = value.reference.replace(/^\{|\}$/g, "");
|
|
78
|
+
if (bare.startsWith("__library:") || bare === "unknown")
|
|
79
|
+
return null;
|
|
80
|
+
try {
|
|
81
|
+
const resolved = resolveReference(value.reference, mode, index);
|
|
82
|
+
// resolveReference throws on cycles / unresolvable, so a returned value
|
|
83
|
+
// is either a literal or another reference. If still a reference,
|
|
84
|
+
// recurse (defensive — resolveReference already chases chains, but the
|
|
85
|
+
// top-level call may return a value with `reference` if mode-fallback
|
|
86
|
+
// routes through an aliased entry).
|
|
87
|
+
if (resolved.reference) {
|
|
88
|
+
return resolveAliasChain(resolved, mode, index);
|
|
89
|
+
}
|
|
90
|
+
return resolved;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
59
96
|
/**
|
|
60
97
|
* Validate every alias in the document. Returns a list of error messages —
|
|
61
98
|
* empty array means all aliases resolve cleanly.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alias-resolver.js","sourceRoot":"","sources":["../../../src/core/tokens/alias-resolver.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"alias-resolver.js","sourceRoot":"","sources":["../../../src/core/tokens/alias-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain JSON formatters — flat and nested.
|
|
3
|
+
*
|
|
4
|
+
* These are dumps without the DTCG `$type`/`$value` envelope, for custom
|
|
5
|
+
* build scripts that just need a key-value map of resolved tokens.
|
|
6
|
+
*
|
|
7
|
+
* Flat shape:
|
|
8
|
+
*
|
|
9
|
+
* {
|
|
10
|
+
* "ds-color-primary": "#4085F2",
|
|
11
|
+
* "ds-spacing-md": "16px",
|
|
12
|
+
* "ds-color-bg--dark": "#0A0A0A"
|
|
13
|
+
* }
|
|
14
|
+
*
|
|
15
|
+
* Multi-mode tokens flatten with `--<mode>` suffix (primary mode keeps
|
|
16
|
+
* the bare name; other modes get suffixed).
|
|
17
|
+
*
|
|
18
|
+
* Nested shape:
|
|
19
|
+
*
|
|
20
|
+
* {
|
|
21
|
+
* "color": {
|
|
22
|
+
* "primary": "#4085F2",
|
|
23
|
+
* "brand": { "primary": "#FF00AA" }
|
|
24
|
+
* },
|
|
25
|
+
* "spacing": { "md": "16px" }
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* Multi-mode tokens become objects: `{ Light: "...", Dark: "..." }`.
|
|
29
|
+
*
|
|
30
|
+
* Aliases resolve to the literal value where possible; cross-library
|
|
31
|
+
* aliases get a `null` (caller can decide how to fill those in).
|
|
32
|
+
*/
|
|
1
33
|
import type { TokenDocument } from "../types.js";
|
|
2
34
|
import type { FormatOptions, FormatResult } from "./index.js";
|
|
3
|
-
export declare function formatJsonFlat(
|
|
4
|
-
export declare function formatJsonNested(
|
|
35
|
+
export declare function formatJsonFlat(doc: TokenDocument, opts: FormatOptions): FormatResult;
|
|
36
|
+
export declare function formatJsonNested(doc: TokenDocument, opts: FormatOptions): FormatResult;
|
|
5
37
|
//# sourceMappingURL=json.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../../../src/core/tokens/formatters/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../../../src/core/tokens/formatters/json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAS,aAAa,EAAwB,MAAM,aAAa,CAAC;AAE9E,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,wBAAgB,cAAc,CAC5B,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,aAAa,GAClB,YAAY,CAyBd;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,aAAa,GAClB,YAAY,CAsBd"}
|
|
@@ -1,8 +1,188 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Plain JSON formatters — flat and nested.
|
|
3
|
+
*
|
|
4
|
+
* These are dumps without the DTCG `$type`/`$value` envelope, for custom
|
|
5
|
+
* build scripts that just need a key-value map of resolved tokens.
|
|
6
|
+
*
|
|
7
|
+
* Flat shape:
|
|
8
|
+
*
|
|
9
|
+
* {
|
|
10
|
+
* "ds-color-primary": "#4085F2",
|
|
11
|
+
* "ds-spacing-md": "16px",
|
|
12
|
+
* "ds-color-bg--dark": "#0A0A0A"
|
|
13
|
+
* }
|
|
14
|
+
*
|
|
15
|
+
* Multi-mode tokens flatten with `--<mode>` suffix (primary mode keeps
|
|
16
|
+
* the bare name; other modes get suffixed).
|
|
17
|
+
*
|
|
18
|
+
* Nested shape:
|
|
19
|
+
*
|
|
20
|
+
* {
|
|
21
|
+
* "color": {
|
|
22
|
+
* "primary": "#4085F2",
|
|
23
|
+
* "brand": { "primary": "#FF00AA" }
|
|
24
|
+
* },
|
|
25
|
+
* "spacing": { "md": "16px" }
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* Multi-mode tokens become objects: `{ Light: "...", Dark: "..." }`.
|
|
29
|
+
*
|
|
30
|
+
* Aliases resolve to the literal value where possible; cross-library
|
|
31
|
+
* aliases get a `null` (caller can decide how to fill those in).
|
|
32
|
+
*/
|
|
33
|
+
import { buildTokenIndex, resolveAliasChain } from "../alias-resolver.js";
|
|
34
|
+
export function formatJsonFlat(doc, opts) {
|
|
35
|
+
const warnings = [];
|
|
36
|
+
const files = [];
|
|
37
|
+
const splitByCollection = opts.target.splitByCollection ?? false;
|
|
38
|
+
const prefix = opts.target.prefix ?? "";
|
|
39
|
+
// Plain JSON has no native alias mechanism — resolve aliases to their
|
|
40
|
+
// literal target so consumers get usable values, not opaque `{ref}` strings.
|
|
41
|
+
const tokenIndex = buildTokenIndex(doc);
|
|
42
|
+
if (splitByCollection) {
|
|
43
|
+
for (const set of doc.sets) {
|
|
44
|
+
files.push({
|
|
45
|
+
path: filenameFor(opts, set, "flat"),
|
|
46
|
+
content: renderFlat([set], prefix, tokenIndex, warnings),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
files.push({
|
|
52
|
+
path: filenameFor(opts, undefined, "flat"),
|
|
53
|
+
content: renderFlat(doc.sets, prefix, tokenIndex, warnings),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return { files, warnings };
|
|
4
57
|
}
|
|
5
|
-
export function formatJsonNested(
|
|
6
|
-
|
|
58
|
+
export function formatJsonNested(doc, opts) {
|
|
59
|
+
const warnings = [];
|
|
60
|
+
const files = [];
|
|
61
|
+
const splitByCollection = opts.target.splitByCollection ?? false;
|
|
62
|
+
const tokenIndex = buildTokenIndex(doc);
|
|
63
|
+
if (splitByCollection) {
|
|
64
|
+
for (const set of doc.sets) {
|
|
65
|
+
files.push({
|
|
66
|
+
path: filenameFor(opts, set, "nested"),
|
|
67
|
+
content: renderNested([set], tokenIndex, warnings),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
files.push({
|
|
73
|
+
path: filenameFor(opts, undefined, "nested"),
|
|
74
|
+
content: renderNested(doc.sets, tokenIndex, warnings),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return { files, warnings };
|
|
78
|
+
}
|
|
79
|
+
function filenameFor(opts, set, shape) {
|
|
80
|
+
if (opts.target.filename)
|
|
81
|
+
return opts.target.filename;
|
|
82
|
+
const parts = [];
|
|
83
|
+
if (set)
|
|
84
|
+
parts.push(slugify(set.name));
|
|
85
|
+
parts.push(`tokens.${shape}`);
|
|
86
|
+
return `${parts.join(".")}.json`;
|
|
87
|
+
}
|
|
88
|
+
function slugify(s) {
|
|
89
|
+
return s
|
|
90
|
+
.trim()
|
|
91
|
+
.toLowerCase()
|
|
92
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
93
|
+
.replace(/^-+|-+$/g, "");
|
|
94
|
+
}
|
|
95
|
+
function renderFlat(sets, prefix, tokenIndex, warnings) {
|
|
96
|
+
const out = {};
|
|
97
|
+
for (const set of sets) {
|
|
98
|
+
const primaryMode = pickPrimaryMode(set.modes);
|
|
99
|
+
for (const token of set.tokens) {
|
|
100
|
+
const baseName = `${prefix}${token.path.map(slugify).join("-")}`;
|
|
101
|
+
for (const [modeName, value] of Object.entries(token.values)) {
|
|
102
|
+
const key = modeName === primaryMode
|
|
103
|
+
? baseName
|
|
104
|
+
: `${baseName}--${slugify(modeName)}`;
|
|
105
|
+
const resolved = resolveValue(value, token, modeName, tokenIndex, warnings);
|
|
106
|
+
if (resolved !== undefined)
|
|
107
|
+
out[key] = resolved;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Sort keys for deterministic output.
|
|
112
|
+
const sorted = Object.fromEntries(Object.entries(out).sort(([a], [b]) => a.localeCompare(b)));
|
|
113
|
+
return JSON.stringify(sorted, null, 2) + "\n";
|
|
114
|
+
}
|
|
115
|
+
function renderNested(sets, tokenIndex, warnings) {
|
|
116
|
+
const out = {};
|
|
117
|
+
for (const set of sets) {
|
|
118
|
+
const isMultiMode = set.modes.length > 1;
|
|
119
|
+
for (const token of set.tokens) {
|
|
120
|
+
let cursor = out;
|
|
121
|
+
for (let i = 0; i < token.path.length - 1; i++) {
|
|
122
|
+
const segment = token.path[i];
|
|
123
|
+
if (!cursor[segment] ||
|
|
124
|
+
typeof cursor[segment] !== "object" ||
|
|
125
|
+
Array.isArray(cursor[segment])) {
|
|
126
|
+
cursor[segment] = {};
|
|
127
|
+
}
|
|
128
|
+
cursor = cursor[segment];
|
|
129
|
+
}
|
|
130
|
+
const leafKey = token.path[token.path.length - 1];
|
|
131
|
+
if (isMultiMode) {
|
|
132
|
+
const modeValues = {};
|
|
133
|
+
for (const [modeName, value] of Object.entries(token.values)) {
|
|
134
|
+
const resolved = resolveValue(value, token, modeName, tokenIndex, warnings);
|
|
135
|
+
if (resolved !== undefined)
|
|
136
|
+
modeValues[modeName] = resolved;
|
|
137
|
+
}
|
|
138
|
+
cursor[leafKey] = modeValues;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
const [onlyModeName, onlyValue] = Object.entries(token.values)[0] ?? [];
|
|
142
|
+
if (onlyValue) {
|
|
143
|
+
const resolved = resolveValue(onlyValue, token, onlyModeName, tokenIndex, warnings);
|
|
144
|
+
if (resolved !== undefined)
|
|
145
|
+
cursor[leafKey] = resolved;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return JSON.stringify(sortKeys(out), null, 2) + "\n";
|
|
151
|
+
}
|
|
152
|
+
function pickPrimaryMode(modes) {
|
|
153
|
+
return modes.find((m) => /^(default|light|value)$/i.test(m)) ?? modes[0];
|
|
154
|
+
}
|
|
155
|
+
function resolveValue(value, token, mode, tokenIndex, warnings) {
|
|
156
|
+
let effective = value;
|
|
157
|
+
if (value.reference) {
|
|
158
|
+
effective = resolveAliasChain(value, mode, tokenIndex);
|
|
159
|
+
if (!effective) {
|
|
160
|
+
const bare = value.reference.replace(/^\{|\}$/g, "");
|
|
161
|
+
const reason = bare.startsWith("__library:") || bare === "unknown"
|
|
162
|
+
? "cross-library alias"
|
|
163
|
+
: "alias target not found";
|
|
164
|
+
warnings.push(`Skipped ${token.path.join(".")} in JSON — ${reason}: ${value.reference}.`);
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!effective || effective.literal === undefined || effective.literal === null) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
if (typeof effective.literal === "number") {
|
|
172
|
+
if (token.type === "dimension")
|
|
173
|
+
return `${effective.literal}px`;
|
|
174
|
+
return effective.literal;
|
|
175
|
+
}
|
|
176
|
+
return effective.literal;
|
|
177
|
+
}
|
|
178
|
+
function sortKeys(obj) {
|
|
179
|
+
if (obj === null || typeof obj !== "object" || Array.isArray(obj))
|
|
180
|
+
return obj;
|
|
181
|
+
const sorted = {};
|
|
182
|
+
const keys = Object.keys(obj).sort();
|
|
183
|
+
for (const k of keys) {
|
|
184
|
+
sorted[k] = sortKeys(obj[k]);
|
|
185
|
+
}
|
|
186
|
+
return sorted;
|
|
7
187
|
}
|
|
8
188
|
//# sourceMappingURL=json.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../../../src/core/tokens/formatters/json.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../../../src/core/tokens/formatters/json.ts"],"names":[],"mappings":"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"}
|