@1agh/maude 0.58.3 → 0.59.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/apps/studio/annotations-layer.tsx +49 -15
- package/apps/studio/bin/_import-asset.mjs +18 -0
- package/apps/studio/bin/_import-figma.mjs +868 -214
- package/apps/studio/bin/_perf-probe-safari.mjs +332 -0
- package/apps/studio/bin/_perf-probe.mjs +228 -0
- package/apps/studio/bin/_perf-shared.mjs +345 -0
- package/apps/studio/bin/_video-playwright.mjs +17 -4
- package/apps/studio/bin/import-figma.sh +10 -1
- package/apps/studio/bin/perf.sh +228 -0
- package/apps/studio/bin/smoke.sh +49 -5
- package/apps/studio/canvas-lib.tsx +148 -6
- package/apps/studio/client/app.jsx +152 -37
- package/apps/studio/client/panels/SyncPanel.jsx +229 -0
- package/apps/studio/client/panels/TimelinePanel.jsx +29 -1
- package/apps/studio/client/panels/timeline-comp-target.js +101 -0
- package/apps/studio/client/styles/3-shell-maude.css +30 -0
- package/apps/studio/client/styles/4-components.css +4 -4
- package/apps/studio/dist/client.bundle.js +772 -772
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/exporters/video-encode-lib.ts +8 -5
- package/apps/studio/exporters/video.ts +10 -0
- package/apps/studio/figma/assets.test.ts +92 -0
- package/apps/studio/figma/assets.ts +63 -9
- package/apps/studio/figma/codegen-client.test.ts +276 -0
- package/apps/studio/figma/codegen-client.ts +509 -0
- package/apps/studio/figma/codegen-fonts.test.ts +103 -0
- package/apps/studio/figma/codegen-fonts.ts +195 -0
- package/apps/studio/figma/codegen-values.test.ts +179 -0
- package/apps/studio/figma/codegen-values.ts +270 -0
- package/apps/studio/figma/endpoints.ts +73 -0
- package/apps/studio/figma/fig-decode.test.ts +702 -0
- package/apps/studio/figma/fig-decode.ts +617 -0
- package/apps/studio/figma/fig-kiwi.ts +410 -0
- package/apps/studio/figma/fig-zip.ts +270 -0
- package/apps/studio/figma/from-codegen.test.ts +408 -0
- package/apps/studio/figma/from-codegen.ts +1103 -0
- package/apps/studio/figma/sanitize.test.ts +69 -0
- package/apps/studio/figma/sanitize.ts +139 -47
- package/apps/studio/figma/tailwind-map.test.ts +142 -0
- package/apps/studio/figma/tailwind-map.ts +545 -0
- package/apps/studio/figma/to-render.ts +25 -3
- package/apps/studio/figma/types.ts +6 -1
- package/apps/studio/http.ts +47 -0
- package/apps/studio/sync/asset-push.ts +346 -38
- package/apps/studio/sync/connection-state.ts +71 -3
- package/apps/studio/sync/index.ts +10 -1
- package/apps/studio/sync/status.ts +18 -0
- package/apps/studio/test/canvas-origin-gate.test.ts +4 -0
- package/apps/studio/test/figma-explode.test.ts +438 -0
- package/apps/studio/test/fixtures/perf-canvas.mjs +201 -0
- package/apps/studio/test/import-figma.test.ts +192 -4
- package/apps/studio/test/sync-asset-push.test.ts +490 -47
- package/apps/studio/test/sync-connection-state.test.ts +66 -0
- package/apps/studio/test/sync-panel-surface.test.ts +90 -0
- package/apps/studio/test/sync-status.test.ts +28 -0
- package/apps/studio/test/timeline-comp-target.test.ts +139 -0
- package/apps/studio/test/video-comp.test.ts +81 -1
- package/apps/studio/test/video-encode-lib.test.ts +63 -0
- package/apps/studio/use-artboard-drag.tsx +37 -3
- package/apps/studio/video-comp.tsx +51 -0
- package/apps/studio/whats-new.json +71 -0
- package/cli/commands/design.mjs +7 -0
- package/cli/commands/kg.mjs +8 -1
- package/cli/commands/kg.test.mjs +24 -0
- package/cli/lib/figma-codegen-reachability.test.mjs +104 -0
- package/cli/lib/figma-import-controls.test.mjs +70 -0
- package/package.json +8 -8
|
@@ -76,6 +76,43 @@ export interface FigmaImportRequest {
|
|
|
76
76
|
dryRun?: boolean;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
export interface FigmaExplodeRequest {
|
|
80
|
+
/** Canvas path RELATIVE to the design root. Never absolute, never `..`. */
|
|
81
|
+
canvas: string;
|
|
82
|
+
/** The `DCArtboard` id. Code-computed at import time, so a strict charset. */
|
|
83
|
+
artboard: string;
|
|
84
|
+
dryRun?: boolean;
|
|
85
|
+
confirmDocument?: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Validate an explode request.
|
|
90
|
+
*
|
|
91
|
+
* Narrower than `parseImportRequest`, because this one MUTATES an existing
|
|
92
|
+
* reviewed, versioned, peer-synced artifact. The caller supplies a target and
|
|
93
|
+
* nothing else: no output path, no node id, no URL, no size. Everything else is
|
|
94
|
+
* read from what the deterministic import already recorded (DDR-219 D8, which
|
|
95
|
+
* inherits DDR-216 D3's "the producer never picks its own target").
|
|
96
|
+
*/
|
|
97
|
+
export function parseExplodeRequest(body: unknown): FigmaExplodeRequest | null {
|
|
98
|
+
if (!body || typeof body !== 'object') return null;
|
|
99
|
+
const b = body as Record<string, unknown>;
|
|
100
|
+
if (typeof b.canvas !== 'string' || b.canvas.length === 0 || b.canvas.length > 512) return null;
|
|
101
|
+
// Traversal is refused HERE as well as by the verb's realpath containment.
|
|
102
|
+
// Two independent checks, because this one is cheap and the failure is total.
|
|
103
|
+
if (b.canvas.includes('..') || b.canvas.startsWith('/') || /^[A-Za-z]:/.test(b.canvas)) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
if (!b.canvas.endsWith('.tsx')) return null;
|
|
107
|
+
if (typeof b.artboard !== 'string' || !/^[a-z0-9-]{1,64}$/.test(b.artboard)) return null;
|
|
108
|
+
return {
|
|
109
|
+
canvas: b.canvas,
|
|
110
|
+
artboard: b.artboard,
|
|
111
|
+
dryRun: b.dryRun === true,
|
|
112
|
+
confirmDocument: b.confirmDocument === true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
79
116
|
export interface FigmaEndpoints {
|
|
80
117
|
/** POST — store a PAT. Returns presence only, never the value. */
|
|
81
118
|
connect(body: unknown): FigmaEndpointResult;
|
|
@@ -87,6 +124,8 @@ export interface FigmaEndpoints {
|
|
|
87
124
|
probe(): Promise<FigmaEndpointResult>;
|
|
88
125
|
/** POST — run an import. Same work the CLI verb does, same guarantees. */
|
|
89
126
|
runImport(body: unknown): Promise<FigmaEndpointResult>;
|
|
127
|
+
/** POST — make ONE already-imported artboard editable via Dev Mode codegen. */
|
|
128
|
+
explode(body: unknown): Promise<FigmaEndpointResult>;
|
|
90
129
|
}
|
|
91
130
|
|
|
92
131
|
/**
|
|
@@ -116,6 +155,10 @@ export interface FigmaEndpointDeps {
|
|
|
116
155
|
runImport?(req: FigmaImportRequest): Promise<{
|
|
117
156
|
summary: Record<string, unknown>;
|
|
118
157
|
}>;
|
|
158
|
+
/** Same injection, same reason. The real implementation is the verb's
|
|
159
|
+
* `explodeArtboard`, so the panel and the CLI cannot drift apart in what
|
|
160
|
+
* they validate, cap or report. */
|
|
161
|
+
explode?(req: FigmaExplodeRequest): Promise<{ summary: Record<string, unknown> }>;
|
|
119
162
|
}
|
|
120
163
|
|
|
121
164
|
export function createFigmaEndpoints(deps: FigmaEndpointDeps = {}): FigmaEndpoints {
|
|
@@ -196,5 +239,35 @@ export function createFigmaEndpoints(deps: FigmaEndpointDeps = {}): FigmaEndpoin
|
|
|
196
239
|
return { status: 500, json: { ok: false, reason: 'failed', error: 'Import failed.' } };
|
|
197
240
|
}
|
|
198
241
|
},
|
|
242
|
+
|
|
243
|
+
async explode(body: unknown): Promise<FigmaEndpointResult> {
|
|
244
|
+
const req = parseExplodeRequest(body);
|
|
245
|
+
if (!req) return { status: 400, json: { error: 'canvas and artboard are required' } };
|
|
246
|
+
if (!deps.explode) {
|
|
247
|
+
return { status: 501, json: { error: 'codegen is not available in this shell' } };
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const { summary } = await deps.explode(req);
|
|
251
|
+
return { status: 200, json: { ok: true, ...summary } };
|
|
252
|
+
} catch (err) {
|
|
253
|
+
// Codegen being unavailable is the COMMON case (no Dev/Full seat, Figma
|
|
254
|
+
// desktop not running, Dev Mode off, wrong tab). It is a 409, not a 500:
|
|
255
|
+
// nothing is wrong with the request or with us. The reason code is the
|
|
256
|
+
// client's OWN enum — `CodegenError.kind` / `CodegenConvertError.reason`
|
|
257
|
+
// are code-owned strings from fixed tables, never upstream text.
|
|
258
|
+
const kind = (err as { kind?: string; reason?: string } | null)?.kind;
|
|
259
|
+
const reason = (err as { reason?: string } | null)?.reason;
|
|
260
|
+
if (typeof kind === 'string') {
|
|
261
|
+
return {
|
|
262
|
+
status: 409,
|
|
263
|
+
json: { ok: false, reason: kind, error: (err as Error).message },
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
if (typeof reason === 'string') {
|
|
267
|
+
return { status: 422, json: { ok: false, reason, error: (err as Error).message } };
|
|
268
|
+
}
|
|
269
|
+
return { status: 500, json: { ok: false, reason: 'failed', error: 'Explode failed.' } };
|
|
270
|
+
}
|
|
271
|
+
},
|
|
199
272
|
};
|
|
200
273
|
}
|