Grida Canvas - IO Figma Fixes & Improvements#481
Conversation
…ing observed patterns and structures
WalkthroughThis PR enhances the Figma clipboard import pipeline by introducing Changes
Sequence DiagramsequenceDiagram
participant User
participant Canvas as Canvas UI
participant Transfer as use-data-transfer
participant Kiwi as iofigma.kiwi
participant Factory as factory.node
participant Scene as Insertable Scene
User->>Canvas: Paste component/instance
Canvas->>Transfer: onDataTransfer (HTML clipboard)
Transfer->>Transfer: readHTMLMessage()
Transfer->>Kiwi: buildClipboardRootNodes({<br/> nodeChanges,<br/> message,<br/> options: {flattenInstances}})
rect rgb(200, 220, 240)
Note over Kiwi,Factory: Root Building Process
Kiwi->>Kiwi: Build GUID maps
Kiwi->>Kiwi: Attach children by parentIndex
alt flattenInstances = true
Kiwi->>Kiwi: Inline SYMBOL subtrees
Kiwi->>Factory: Create flattened instances
Factory->>Factory: Apply symbol overrides
Factory->>Factory: Scale vector networks<br/>(normalizedSize → node space)
Factory-->>Kiwi: Return processed nodes
else flattenInstances = false
Kiwi-->>Kiwi: Return root structure as-is
end
end
Kiwi-->>Transfer: rootNodes[]
Transfer->>Transfer: Validate roots found
Transfer->>Scene: Insert root nodes
Scene-->>Canvas: Nodes added to scene
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes The PR introduces substantial new functionality across the Figma IO library with heterogeneous changes: core library refactoring with new types and functions, vector scaling logic, instance flattening implementation, clipboard conversion pipeline changes, and an extensive fixture/test suite. Logic density is moderate-to-high in Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…including support for root-level overrides and flattening instances
… and scaling implications for Figma nodes
…zed size to improve rendering accuracy
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
packages/grida-canvas-io-figma/lib.ts (3)
1952-2025: Root-level symbolOverrides patching for instances is minimal but well-scopedThe new
instanceconstruction:
- Builds a full
InstanceNodeonce and then conditionally applies a “root patch” when the firstsymbolOverridesentry lacksguid/type/parentIndex, which matches the clipboard payloads you’re targeting.- Avoids touching targeted overrides (with
guid), which are instead consumed later byflattenInstancesInPlaceviasymbolOverrideByGuid.This strikes a good balance between fixing real clipboard cases and not over-implementing the full override system prematurely. The inline
TODO(kiwi-overrides)is accurate and keeps expectations clear.
2057-2117: Vector network scaling hook invectorNodeis correct and matches the new testsWiring
parseVectorNetworkBlobthroughscaleVectorNetworkFromNormalizedSizebefore emitting anX_VECTORnode:
- Uses
normalizedSizeandsizeto compute per-axis scale factors and applies them uniformly to vertices and tangents.- Falls back to scale 1 when either dimension is missing or zero, which is safe and predictable.
- Preserves the old
VECTORfallback path (with emptypathstrings) when no blob is available, so existing behavior is unchanged there.The new vector-network test exercises this path and should catch regressions in the coordinate-space mapping.
2298-2637: Instance flattening and clipboard/page tree builders are thoughtfully structuredThe new
BuildTreeOptions+ helpers (buildGuidToKiwiMap,buildFlatFigmaNodes,buildChildrenRelationsInPlace,flattenInstancesInPlace,buildClipboardRootNodes,buildCanvasRootNodes) form a coherent pipeline:
- Building flat REST/IR nodes once and reusing
guidToNode/guidToKiwiavoids repeated conversion.- Child attachment via
parentIndex.guid+ lexicographicpositionsorting mirrors Figma’s ordering model.flattenInstancesInPlace+cloneTreeWithNewIdsAndFlattenInstancesproperly:
- Inline component trees for
INSTANCEs whenflattenInstancesis enabled.- Guard against component cycles via
componentStack.- Apply targeted overrides by guid during cloning, while preserving root-level patches applied in
instance().The clipboard builder also correctly excludes children of internal-only canvases from the roots, treating those canvases as a component repository.
If you later need full override semantics (swaps, nested instance overrides, non-paint fields), you already have clear extension points and TODOs.
editor/grida-canvas-react/use-data-transfer.ts (1)
177-183: Centralized clipboard root-building looks correct and simplifies this pathUsing
iofigma.kiwi.buildClipboardRootNodeswith{ nodeChanges, message: parsed.message, options: { flattenInstances: true } }cleanly replaces the bespoke root-detection logic, and the updated error message gives much better feedback (total nodes vs insertable roots). No functional issues spotted; this should also keep behavior aligned with the shared iofigma build pipeline going forward.Also applies to: 185-189
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-text-overrides.test.ts (1)
5-8: Consider tracking the fixture replacement as technical debt.The comment correctly identifies that this test uses handcrafted/mocked data instead of a real Figma clipboard fixture. While the test validates the override logic in isolation, it would be more robust with a real-world fixture.
Do you want me to open an issue to track adding a real clipboard fixture with text overrides? This would ensure the test validates against actual Figma clipboard format.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
docs/wg/feat-fig/glossary/fig.kiwi.mdeditor/grida-canvas-hosted/playground/examples.tseditor/grida-canvas-react/use-data-transfer.tseditor/public/examples/canvas/poster-happy-new-year-2026.gridafixtures/test-fig/L0/components.figfixtures/test-fig/clipboard/README.mdfixtures/test-fig/clipboard/component-component-blue.clipboard.htmlfixtures/test-fig/clipboard/component-component-instance-blue-with-overrides.clipboard.htmlfixtures/test-fig/clipboard/component-component-instance-blue.clipboard.htmlfixtures/test-fig/clipboard/component-component-instance-red-with-overrides.clipboard.htmlfixtures/test-fig/clipboard/component-component-instance-red.clipboard.htmlfixtures/test-fig/clipboard/component-component-red.clipboard.htmlfixtures/test-fig/clipboard/component-component-set-component-blue.clipboard.htmlfixtures/test-fig/clipboard/component-component-set-component-instance-blue-with-overrides.clipboard.htmlfixtures/test-fig/clipboard/component-component-set-component-instance-blue.clipboard.htmlfixtures/test-fig/clipboard/component-component-set-component-instance-red-with-overrides.clipboard.htmlfixtures/test-fig/clipboard/component-component-set-component-instance-red.clipboard.htmlfixtures/test-fig/clipboard/component-component-set-component-red.clipboard.htmlfixtures/test-fig/clipboard/component-component-set.clipboard.htmlfixtures/test-fig/clipboard/frame-with-stroke.clipboard.htmlpackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-components.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-overrides.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-text-overrides.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.fig.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.vector-network.test.tspackages/grida-canvas-io-figma/lib.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript 5 as the main language for most apps
Use Lucide or Radix Icons for icons
Files:
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.vector-network.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-overrides.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-text-overrides.test.tseditor/grida-canvas-hosted/playground/examples.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-components.test.tseditor/grida-canvas-react/use-data-transfer.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.fig.test.tspackages/grida-canvas-io-figma/lib.ts
{editor/**/*.{ts,tsx},packages/grida-canvas-*/**/*.{ts,tsx}}
📄 CodeRabbit inference engine (AGENTS.md)
Use DOM (plain DOM as canvas) for website builder canvas, bound with React
Files:
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.vector-network.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-overrides.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-text-overrides.test.tseditor/grida-canvas-hosted/playground/examples.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-components.test.tseditor/grida-canvas-react/use-data-transfer.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.fig.test.tspackages/grida-canvas-io-figma/lib.ts
packages/grida-canvas-*/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Packages under /packages/grida-canvas-* power the canvas; some are published to npm, refer to individual package README
Files:
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.vector-network.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-overrides.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-text-overrides.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-components.test.tspackages/grida-canvas-io-figma/__tests__/iofigma.kiwi.fig.test.tspackages/grida-canvas-io-figma/lib.ts
docs/**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
Documentation source of truth is in the ./docs directory; deployment is handled by apps/docs
Files:
docs/wg/feat-fig/glossary/fig.kiwi.md
docs/{wg,reference}/**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
Only actively maintain docs/wg/** and docs/reference/** directories; see docs/AGENTS.md for contribution scope
Files:
docs/wg/feat-fig/glossary/fig.kiwi.md
editor/grida-*/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use /editor/grida-* directories to isolate domain-specific modules; promote well-defined modules to /packages
Files:
editor/grida-canvas-hosted/playground/examples.tseditor/grida-canvas-react/use-data-transfer.ts
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to packages/grida-canvas-*/**/*.{ts,tsx,js,jsx} : Packages under /packages/grida-canvas-* power the canvas; some are published to npm, refer to individual package README
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas/AGENTS.md:0-0
Timestamp: 2025-12-20T08:11:16.201Z
Learning: Applies to crates/grida-canvas/**/*.grida : Validate .grida files using the `tool_io_grida` CLI tool to check file structure, parse all nodes, and detect parsing errors
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas/AGENTS.md:0-0
Timestamp: 2025-12-20T08:11:16.201Z
Learning: Applies to crates/grida-canvas/**/*.rs : Run `cargo fmt` to maintain code formatting standards
📚 Learning: 2025-12-01T00:22:19.083Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-wasm/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:19.083Z
Learning: Applies to crates/grida-canvas-wasm/**/main.rs : Update `grida-canvas-wasm.d.ts` TypeScript definitions file when new APIs are introduced via `main.rs`
Applied to files:
editor/grida-canvas-hosted/playground/examples.tspackages/grida-canvas-io-figma/lib.ts
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to packages/grida-canvas-*/**/*.{ts,tsx,js,jsx} : Packages under /packages/grida-canvas-* power the canvas; some are published to npm, refer to individual package README
Applied to files:
editor/grida-canvas-hosted/playground/examples.tspackages/grida-canvas-io-figma/lib.ts
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to {editor/**/*.{ts,tsx},packages/grida-canvas-*/**/*.{ts,tsx}} : Use DOM (plain DOM as canvas) for website builder canvas, bound with React
Applied to files:
editor/grida-canvas-react/use-data-transfer.ts
📚 Learning: 2025-12-01T00:22:56.899Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: editor/app/(tools)/tools/halftone/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:56.899Z
Learning: Applies to editor/app/(tools)/tools/halftone/app/(tools)/tools/halftone/_page.tsx : When adding new shape types, update the Shape type union, add cases in drawShape() function, add cases in shapeToSVG() function, and add SelectItem in UI
Applied to files:
packages/grida-canvas-io-figma/lib.ts
📚 Learning: 2025-12-01T00:22:56.899Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: editor/app/(tools)/tools/halftone/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:56.899Z
Learning: Applies to editor/app/(tools)/tools/halftone/app/(tools)/tools/halftone/_page.tsx : Use Canvas 2D API with path commands for rendering geometric shapes (circle, square, triangle, etc.)
Applied to files:
packages/grida-canvas-io-figma/lib.ts
📚 Learning: 2025-12-01T00:22:56.899Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: editor/app/(tools)/tools/halftone/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:56.899Z
Learning: Applies to editor/app/(tools)/tools/halftone/app/(tools)/tools/halftone/_page.tsx : For SVG export, convert circles to <circle> elements, rectangles to <rect> elements, and polygons to <polygon> elements with calculated points
Applied to files:
packages/grida-canvas-io-figma/lib.ts
🧬 Code graph analysis (5)
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.vector-network.test.ts (2)
packages/grida-canvas-io-figma/fig-kiwi/index.ts (2)
readFigFile(250-283)getBlobBytes(344-351)packages/grida-canvas-io-figma/index.ts (1)
iofigma(7-7)
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-overrides.test.ts (3)
editor/eslint.config.mjs (1)
__dirname(6-6)packages/grida-canvas-io-figma/index.ts (1)
iofigma(7-7)crates/grida-canvas/src/node/scene_graph.rs (1)
roots(206-208)
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-text-overrides.test.ts (2)
crates/grida-canvas/src/node/scene_graph.rs (1)
roots(206-208)packages/grida-canvas-io-figma/index.ts (1)
iofigma(7-7)
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-components.test.ts (3)
editor/eslint.config.mjs (1)
__dirname(6-6)crates/grida-canvas/src/node/scene_graph.rs (1)
roots(206-208)packages/grida-canvas-io-figma/index.ts (1)
iofigma(7-7)
packages/grida-canvas-io-figma/lib.ts (3)
packages/grida-canvas-schema/grida.ts (1)
NodeChange(1319-1319)crates/grida-canvas/src/painter/layer.rs (1)
paints(220-224)packages/grida-canvas-io-figma/fig-kiwi/index.ts (2)
readFigFile(250-283)ParsedFigmaArchive(82-85)
🪛 Gitleaks (8.30.0)
fixtures/test-fig/clipboard/component-component-set-component-blue.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-instance-blue-with-overrides.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-instance-blue.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-set-component-instance-blue.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-set-component-instance-red-with-overrides.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-set-component-instance-red.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-instance-red.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-instance-red-with-overrides.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-set.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-blue.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-set-component-red.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/frame-with-stroke.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
fixtures/test-fig/clipboard/component-component-set-component-instance-blue-with-overrides.clipboard.html
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (35)
fixtures/test-fig/L0/components.fig (1)
1-3: Git LFS pointer update is valid.The Figma fixture file has been updated with a new object ID and increased size (28,343 → 29,545 bytes), which aligns with the PR's introduction of expanded clipboard test fixtures. The Git LFS pointer format is correct and valid.
editor/grida-canvas-hosted/playground/examples.ts (1)
32-36: Entry is correctly structured and the referenced file exists.The new example entry at lines 32-36 follows the established pattern perfectly, with the
.gridafile already present ateditor/public/examples/canvas/poster-happy-new-year-2026.grida. The id, name, and url properties are consistent with all other entries in the array.fixtures/test-fig/clipboard/README.md (2)
65-127: Excellent payload structure documentation with clear verification.The detailed documentation of Component/Instance and Component set payload structures is technically accurate and well-organized. The distinction between user-facing canvas and internal-only canvas is clearly explained, and the fixture verification sections provide specific references for validation.
Particularly strong points:
- Clear explanation of INSTANCE-to-SYMBOL linkage via
symbolData.symbolID- Practical patterns covering all three clipboard scenarios (container, variant, instance)
- Systematic documentation of both component sets (FRAME) and variants (SYMBOL)
- Verification sections cite specific fixtures for reproducibility
43-64: Comprehensive and well-structured fixture table.The expanded Contents table clearly documents all clipboard fixture scenarios with appropriate categorization by source and usage. The systematic naming convention (blue/red variants, with/without overrides) makes the fixture coverage easy to understand. All referenced fixture files exist at the expected paths.
docs/wg/feat-fig/glossary/fig.kiwi.md (3)
266-292: Clear documentation of component-set clipboard patterns with fixture references.The new subsection documenting how component sets appear in clipboard payloads is well-structured and practical. The three scenarios (container copy, variant copy, instance copy) are clearly differentiated, and the fixture references are specific and helpful for verification.
293-336: Comprehensive guide to components and instances in clipboard payloads.The new "Components & Instances (clipboard payloads)" section effectively bridges glossary documentation and practical clipboard handling. The structure (node types → internal-only canvas → observed patterns) flows logically, and the four distinct scenarios are clearly explained with specific fixture references.
Strengths:
- Explains the role of internal-only canvas for non-user-facing definitions
- Clarifies the INSTANCE-to-SYMBOL linkage across all scenarios
- Fixture references are comprehensive and specific
343-358: Technically sound explanation of vector coordinate space mapping.The new subsection on vector network coordinate space clearly documents the
normalizedSizevs.sizedistinction and provides practical scaling guidance with proper mathematical notation. This directly supports the PR's vector scaling improvements.The explanation effectively conveys:
- Why the coordinate space matters (avoiding mis-positioned/mis-sized vectors)
- How to apply scaling to both vertex positions and segment tangents
- The caveat about potential bbox origin translations
All referenced fixture files exist at their documented paths.
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.fig.test.ts (1)
193-276: Good, focused regression coverage for root merge / ID-collision bugThe mock
FigPageand assertions accurately exercise the multi-root merge path withoutnode_id_generator, and will catch regressions in the shared ID generator logic inconvertPageToScene.fixtures/test-fig/clipboard/component-component-set-component-red.clipboard.html (1)
1-5: Static Figma clipboard fixture looks fineStructure matches existing clipboard fixtures (charset + figmeta + figma buffer), and the large base64 payload is expected binary scene data. The reported “generic API key” here is a typical false positive on opaque fixture blobs rather than an actual secret.
fixtures/test-fig/clipboard/component-component-set-component-instance-blue.clipboard.html (1)
1-5: Clipboard instance (blue) fixture is consistent and self-containedThe markup follows the established clipboard-fixture pattern and safely encapsulates the binary payload for tests.
fixtures/test-fig/clipboard/frame-with-stroke.clipboard.html (1)
1-5: Frame-with-stroke fixture correctly follows existing clipboard formatLooks appropriate for exercising stroke handling on clipboard-imported frames; no issues.
fixtures/test-fig/clipboard/component-component-set-component-blue.clipboard.html (1)
1-5: Component-set (blue) clipboard fixture is well-formedStatic data-only fixture, consistent with other component/component-set clipboard assets.
fixtures/test-fig/clipboard/component-component-blue.clipboard.html (1)
1-5: Component (blue) clipboard fixture matches the rest of the test corpusNo issues; this extends coverage for component clipboard scenarios.
packages/grida-canvas-io-figma/lib.ts (5)
1007-1023: Stroke trait inclusion for FRAME / COMPONENT / INSTANCE is a sensible extensionAdding
...stroke_trait(node)to these container types ensures stroke metadata is preserved consistently for frames, components, and instances, aligning them with shapes like rectangles/ellipses. Downstream Grida nodes now get a uniform stroke representation without special-casing these node types.
2139-2199:scaleVectorNetworkFromNormalizedSizeimplementation looks mathematically soundThe scaler:
- Computes
sx/syassize / normalizedSizewith robust guards against zero/undefined.- Returns the original network when both scales are 1, avoiding unnecessary allocations.
- Scales both vertex positions and segment tangents, leaving region topology untouched, which is exactly what’s needed.
Given the surrounding comments and test coverage, this is a solid, self-contained utility.
2667-2733: PropagatingBuildTreeOptionsthroughparseFile/extractPages/buildPageTreeis cleanThe updated signatures:
- Keep
optionsoptional with a default{}on bothparseFileandFigImporter.parseFile, so all existing call sites remain valid.- Plumb those options down into
buildPageTree→buildCanvasRootNodes, unifying the tree-building behavior between .fig imports and clipboard handling.This is a straightforward and backwards-compatible extension of the API.
2738-2793: Sharednode_id_generatorinconvertPageToScenecorrectly fixes root-merge collisionsThe new logic:
- Creates a
sharedNodeIdGenerator(either the caller’s generator or a Date.now() + counter fallback) and injects it into a derivedsharedContext.- Ensures every
restful.factory.documentinvocation in the loop uses this shared generator instead of per-call fallbacks, avoiding ID collisions when multiple roots are converted and then merged.- Leaves
gradient_id_generatorand other context fields untouched.This directly addresses the regression covered by the new “should not drop roots when merging” test.
2800-2813: FigImporter static API remains backwards compatible while exposing optionsThe class wrapper now simply forwards
optionsto the underlying functions:
FigImporter.parseFile(fileData, options)→kiwi.parseFile(fileData, options)FigImporter.convertPageToScene(page, context)→kiwi.convertPageToScene(page, context)Callers not passing an options object still get the same behavior, while newer callers can opt into
flattenInstancesand related behaviors without touching existing code.packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.vector-network.test.ts (1)
1-93: Strong regression test for vectorNetwork scaling from normalizedSize to sizeThis test:
- Carefully selects a VECTOR candidate with meaningful
normalizedSizevssizedifferences.- Validates the
bboxof the raw parsed network against the bbox of the scaled network produced byiofigma.kiwi.factory.node.- Asserts both dimensions and origin within a tight tolerance, which will catch subtle mistakes in the scaling logic.
The explicit guards and fixture-based approach make this a solid, low-noise regression test.
fixtures/test-fig/clipboard/component-component-red.clipboard.html (1)
1-5: Clipboard fixture structure LGTMHTML markup (figmeta metadata, figma buffer, and whitespace span) is consistent with the existing clipboard fixtures and suitable for automated tests.
fixtures/test-fig/clipboard/component-component-instance-red.clipboard.html (1)
1-5: Instance clipboard fixture looks validFollows the same figmeta + figma buffer pattern as the other fixtures; appropriate for exercising component-instance clipboard scenarios in tests.
fixtures/test-fig/clipboard/component-component-set-component-instance-red.clipboard.html (1)
1-5: Component‑set/instance clipboard fixture LGTMWell-formed clipboard HTML fixture (charset, figmeta, figma buffer, whitespace span) matching the expected structure for component‑set + instance tests.
fixtures/test-fig/clipboard/component-component-set.clipboard.html (1)
1-5: Component‑set clipboard fixture is consistent with the suiteMatches the other fixtures’ structure and is appropriate for testing component‑set root construction.
fixtures/test-fig/clipboard/component-component-instance-blue.clipboard.html (1)
1-5: Blue instance clipboard fixture looks goodStructurally identical to the red instance fixture with different payload, which is useful for variant coverage in tests.
fixtures/test-fig/clipboard/component-component-instance-red-with-overrides.clipboard.html (1)
1-5: Overrides-focused instance fixture is well-formedThis clipboard HTML follows the established figmeta/figma-buffer pattern and is appropriate for exercising symbol override behavior in tests.
fixtures/test-fig/clipboard/component-component-instance-blue-with-overrides.clipboard.html (1)
1-5: Blue instance + overrides fixture LGTMConsistent HTML/clipboard structure with the other fixtures; suitable for override-related clipboard tests.
fixtures/test-fig/clipboard/component-component-set-component-instance-red-with-overrides.clipboard.html (1)
1-5: LGTM! Valid test fixture with false positive security warning.This HTML fixture file contains base64-encoded Figma clipboard data for testing component-set instance scenarios with overrides. The static analysis warning about a "Generic API Key" is a false positive—this is legitimate test data, not sensitive credentials.
fixtures/test-fig/clipboard/component-component-set-component-instance-blue-with-overrides.clipboard.html (1)
1-5: LGTM! Valid test fixture with false positive security warning.This HTML fixture file contains base64-encoded Figma clipboard data for testing the blue variant of component-set instance scenarios with overrides. The static analysis warning is a false positive—this is test fixture data, not sensitive credentials.
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-components.test.ts (3)
1-12: LGTM! Clean imports and fixture path setup.The imports and fixture path constants are well-organized and follow project conventions. Using
__dirnamefor relative fixture paths is appropriate.
14-41: LGTM! Component definition tests are well-structured.The tests for component definition copies follow a clear pattern and correctly validate that:
- A single COMPONENT root is returned
- The
flattenInstances: trueoption is properly appliedThe parallel blue/red test structure provides good coverage.
43-74: LGTM! Instance copy tests correctly validate flattening behavior.The tests for instance copies properly validate that:
- A single INSTANCE root is returned
- Internal SYMBOL masters are excluded from roots
- The helpful comment on lines 55-57 explains the expected behavior regarding internal-only canvas nodes
The negative assertion
expect(roots.some((n) => n.type === "COMPONENT")).toBe(false)is particularly valuable for ensuring internal masters don't leak into the root set.packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-text-overrides.test.ts (1)
70-87: LGTM! Test logic correctly validates text override behavior.Despite using mocked data, the test effectively validates that:
buildClipboardRootNodesreturns a single INSTANCE root withflattenInstances: true- TEXT node overrides from
symbolOverridesare correctly applied- The overridden text characters are present in the final structure
The test assertions are clear and appropriate.
packages/grida-canvas-io-figma/__tests__/iofigma.kiwi.clipboard-overrides.test.ts (3)
1-16: LGTM! Clean setup with helpful utility function.The imports, fixture paths, and
findInstanceNchelper function are well-organized. The FILES array provides good coverage across blue/red and component/component-set variants.
18-45: LGTM! Comprehensive validation of paint override application.The test correctly validates that
symbolData.symbolOverridesare applied to INSTANCE nodes by:
- Testing all fixture variants in a loop
- Checking that override paints (fills/strokes) are present when defined
- Using conditional assertions to handle cases where paints may be absent
The pattern of only asserting on fills/strokes when the override defines them is appropriate.
47-76: LGTM! Excellent validation of override preservation during flattening.This test ensures that paint overrides are not lost when
buildClipboardRootNodesflattens instances. The test:
- Validates the expected single INSTANCE root structure
- Confirms internal master nodes are excluded (comment on line 58 helpfully explains why)
- Verifies override-produced paints survive the flattening process
The pattern of re-checking overrides after flattening provides strong confidence in the implementation.
Release Notes
New Features
Bug Fixes
Documentation
Tests