mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 23:00:03 +00:00
fix(core,cli): figma IMAGE fills dropped, rasterize double-paint, tokens false-success
nodeToHtml routed rasterize eligibility off node.type alone, so a RECTANGLE/FRAME with an IMAGE fill fell through to the generic <div> path — fillCss() has no IMAGE case, so it rendered an empty box. IMAGE-filled nodes now route to rasterize like vectors, regardless of node.type. Rasterized nodes (vectors, now image fills too) were also getting their own fill/corner-radius CSS applied on top of the already- rendered <img> — a flat color block behind/around the real art, flattening non-rectangular shapes into rounded rects. decorationCss now skips background and corner-radius/clip for rasterized nodes; opacity and effects still apply since those aren't baked into the export. tokens.ts's styles-fallback path hardcoded entries: [] regardless of how many published styles were actually found, so the CLI printed "recorded published style metadata instead" even when styles() returned zero results. Added styleCount to the result so the message reflects what happened, and points at the MCP get_variable_defs fallback when there's nothing to fall back to. Co-Authored-By: Claude Opus <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus
parent
43af582534
commit
c8eff1a4ba
@@ -57,12 +57,24 @@ describe("runTokensImport", () => {
|
||||
const out = await runTokensImport("FILE", { projectDir: dir, client: gated });
|
||||
expect(out.mode).toBe("styles");
|
||||
expect(out.entries).toEqual([]);
|
||||
expect(out.styleCount).toBe(1);
|
||||
const sidecar = JSON.parse(readFileSync(join(dir, "figma-tokens.json"), "utf8")) as {
|
||||
tokens: Array<{ name: string; type: string }>;
|
||||
};
|
||||
expect(sidecar.tokens[0]).toMatchObject({ name: "Primary", type: "style:FILL" });
|
||||
});
|
||||
|
||||
it("reports styleCount 0 when the file has no published styles — never a false success", async () => {
|
||||
const gatedNoStyles = client({
|
||||
variables: () =>
|
||||
Promise.reject(new FigmaClientError("REQUIRES_ENTERPRISE", "enterprise only", 403)),
|
||||
styles: () => Promise.resolve([]),
|
||||
});
|
||||
const out = await runTokensImport("FILE", { projectDir: dir, client: gatedNoStyles });
|
||||
expect(out.mode).toBe("styles");
|
||||
expect(out.styleCount).toBe(0);
|
||||
});
|
||||
|
||||
it("propagates non-enterprise failures", async () => {
|
||||
const broken = client({
|
||||
variables: () => Promise.reject(new FigmaClientError("RATE_LIMITED", "429", 429)),
|
||||
|
||||
@@ -30,6 +30,10 @@ export interface TokensImportResult {
|
||||
mode: "variables" | "styles";
|
||||
entries: CompositionVariableEntry[];
|
||||
sidecarPath: string;
|
||||
/** styles mode only: how many published styles were actually found —
|
||||
* entries is always [] in this mode (style values resolve later, at
|
||||
* component-import time), so this is what tells success from empty. */
|
||||
styleCount?: number;
|
||||
}
|
||||
|
||||
export async function runTokensImport(
|
||||
@@ -68,7 +72,7 @@ export async function runTokensImport(
|
||||
})),
|
||||
};
|
||||
writeFileSync(sidecarPath, JSON.stringify(sidecar, null, 2) + "\n");
|
||||
return { mode: "styles", entries: [], sidecarPath };
|
||||
return { mode: "styles", entries: [], sidecarPath, styleCount: styles.length };
|
||||
}
|
||||
|
||||
export default defineCommand({
|
||||
@@ -84,7 +88,9 @@ export default defineCommand({
|
||||
const result = await runTokensImport(args.ref, { projectDir: args.dir, client });
|
||||
if (result.mode === "styles") {
|
||||
console.log(
|
||||
"variables are Enterprise-gated on this plan — recorded published style metadata instead (style values resolve at component-import time)",
|
||||
(result.styleCount ?? 0) > 0
|
||||
? `variables are Enterprise-gated on this plan — recorded ${result.styleCount} published style(s) instead (style values resolve at component-import time)`
|
||||
: "variables are Enterprise-gated on this plan, and this file has no published library styles to fall back to — nothing recorded. Publish the file's styles to a team library, or read variables via the Figma MCP connector's get_variable_defs instead (works on any plan, rate-limited).",
|
||||
);
|
||||
}
|
||||
console.log(`wrote ${result.sidecarPath} (${result.mode})`);
|
||||
|
||||
Reference in New Issue
Block a user