Skip to content

Replace Figma inspector with offline preview and project export - #13287

Open
NigelBreslaw wants to merge 49 commits into
masterfrom
nigel/replace-figma-plugin
Open

NigelBreslaw wants to merge 49 commits into
masterfrom
nigel/replace-figma-plugin

Conversation

@NigelBreslaw

@NigelBreslaw NigelBreslaw commented Sep 8, 2026

Copy link
Copy Markdown
Member

Replace the Figma inspector with an offline Slint preview and editable project export, imported from standalone snapshot 397261b without its history. The plugin captures the selection once and converts it into Slint for preview, copying and project export.

Keep the published Figma to Slint identity and plugin ID, native codegen, VS Code capability, and Use Variables preference (off by default). Native codegen generates root-only snippets; preview/export handles the full selected tree.

Build integration

The plugin now follows SlintPad: wasm-pack builds api/wasm-interpreter in the current checkout, and Vite bundles the result. There is no separate runtime pin, source checkout or custom artifact cache. The UI embeds the interpreter and both workers, with no external resource requests. Nightly packaging reuses the existing WASM workflow artifact.

Dependencies use the workspace catalog where available, including TypeScript 6 and Vite 8. ZIPs retain plugin identity, notices, dependency inventory, checksums and repository/channel metadata.

Review order

The initial six commits separate runtime infrastructure, capture, conversion/export, preview UI, published codegen compatibility, and distribution cutover. Subsequent commits simplify documentation and replace the initial runtime infrastructure:

  • 4fa2512966 — build the interpreter from the current workspace; remove the separate pin/cache system.
  • c13015698f — restore Vite, inline workers and single-file UI; clean up Knip configuration.
  • 467939a07a — simplify CI and reuse nightly WASM artifacts. The only added path filter is api/wasm-interpreter/**.

Validation

  • Full pnpm verify: 293 unit tests and 18 Chromium browser tests passed, plus formatting, lint, types, scoped Knip, spelling, bundle and ZIP contracts.
  • Final root pnpm knip: passes without warnings after removing obsolete configuration and excluding generated wasm-bindgen output.
  • Fresh workspace interpreter build, incremental rebuild, both Vite watch targets, and a second checkout with spaces and Unicode exercised successfully.
  • REUSE lint passed; changed workflow YAML parsed successfully.
  • Browser and Figma Desktop previews visually inspected. Live Dev Mode and VS Code codegen qualification remain outstanding because of account/extension availability.

Vite explicitly warns about # in project-root paths; an extra test confirmed that upstream limitation. Paths containing spaces and Unicode passed. CI results will provide Ubuntu validation after this push.

Comment thread tools/figma-inspector/scripts/build-slint.mjs
working-directory: tools/figma-inspector/zip
- name: Archive zip
uses: actions/upload-artifact@v7
run: pnpm test:nightly

@tronical tronical Sep 16, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this might not work in the CI. test:nightly calls zip:nightly, which merely calls build, but I think it's missing the build:slint step.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stand corrected, I missed the needs: [wasm].

NigelBreslaw and others added 22 commits September 18, 2026 10:31
Keep the existing plugin entry points while adding clean runtime preparation, artifact cache validation, and path portability tests. Use the monorepo dependency catalog, including TypeScript 6 and Vitest 4.

Validation: 17 infrastructure tests passed; existing Vite build passed; fresh pinned checkout prepared and cached interpreter restored.
Import the capture boundary, versioned JSON, asset transport, and authored regression fixtures from standalone snapshot 397261b. Keep the existing plugin entry points active.

Validation: TypeScript 6 check and 108 replacement unit tests passed.
Import pure conversion, component and token generation, and self-contained project export with fixture-based regressions. No published entry point changes yet.

Validation: TypeScript 6 check and 265 replacement unit tests passed.
Add replacement build and verification commands without changing the published build. Include worker conversion, preview lifecycle, raw clipboard and project export, and native root-only snippet foundations.

Use the selected Cargo binary for dependency notices. Validation: TypeScript 6, artifact and bundle contracts, 303 unit tests, and 18 Chromium browser tests passed with catalog tooling.
Retain the Figma to Slint ID and VS Code capability. Honor the native useVariables preference using captured variable metadata and pure root-binding substitution. Keep the published variable path naming and diagnose unsupported bindings without discarding literals.

Validation: TypeScript 6 and 23 codegen tests passed; production/development manifest and sandbox contracts passed. Worktree preview inspected in Figma Desktop. Live Dev Mode is gated by the current document's locked team; no Figma VS Code extension is installed.
Replace the old React inspector and variable-export workflow with preview and project export. Use catalog tooling, scoped workspace checks, explicit nightly packaging, strict release validation, and portable notices and checksums. Update Ubuntu CI, nightly artifacts and maintenance documentation.

Validation: pnpm verify passes 310 unit tests and 18 Chromium browser tests plus formatting, lint, TypeScript 6, Knip, spelling, bundle and packaging contracts. Frozen catalog install and REUSE pass. Fresh pinned source preparation, warm artifact restoration and a build path containing spaces were exercised. Desktop preview was inspected; live Dev Mode and VS Code codegen remain platform checks. No remote CI was run.
Keep installation, usage and development in a short README. Consolidate release and nightly instructions in PUBLISH.md and remove the redundant architecture and release documents.

Validation: formatting and spelling pass; no references to removed documents remain. Full verification stops at the existing dirty pinned runtime checkout, which was left untouched.
Use SlintPad's wasm-pack commands and api/wasm-interpreter/pkg. Remove the separately pinned checkout, artifact cache and pin-validation machinery. Import the repository grammar directly and record repository revision and package version in ZIP provenance.

Validation: the fresh workspace interpreter build and incremental rebuild passed; pnpm verify passed all remaining unit tests and 18 browser tests, including raster references, with the existing bundler.
Build the sandbox as an IIFE and inline the UI, interpreter and workers with Vite. Replace custom worker-source injection and the watcher with Vite's inline workers and build watchers. Keep manifest identity and dependency notices; prevent duplicate WASM embedding.

Validation: pnpm verify passes 293 unit and 18 browser tests, including the no-external-resource assertion and raster checks. Sandbox/codegen contracts and both ZIP modes pass. Vite watch rebuilds both targets; root pnpm knip passes after removing stale configuration and excluding generated wasm-bindgen exports.
Use the repository Rust setup for plugin verification and consume the existing wasm artifact for nightly packaging. Remove the custom runtime cache and duplicate nightly compilation. Add only api/wasm-interpreter to the existing Figma path filter.

Validation: workflow YAML parses, REUSE passes, and root pnpm knip passes without warnings. Full plugin verification passed after the Vite migration; a second checkout with spaces and Unicode builds successfully. Vite warns about and does not support a # character in its project root.
Keep unconditional Flexbox layout owners around structural alternatives so active branches contribute natural size at component roots and nested Hug rows.

Add authored geometry and responsive-property regressions for preview and export. The old generator fails all four geometry regressions. pnpm verify passes 297 unit and 26 browser tests; root pnpm knip is clean. Figma verification remains with the reviewer.
Keep layout enums and typed expressions as bindings, retain paint helper roles, and reserve Slint states for explicit state axes. Name shared predicates, reuse their inverses, and simplify structural branches within their reachable variant context. Add private structural components and an occurrence-specialized emission mode through the same renderer.

Validate sparse predicates, independent layout/state axes, named inverses, private component boundaries, and unchanged intrinsic sizing with authored unit and browser regressions.
Transport the internal render program alongside readable source using one shared asset table. Keep raw copy and native export tied to the reusable output, with the existing revision, blanking, and failure rules.

Verify exact pixels for conditional root, inner-row, and raster fixtures, plus source/copy separation, failed render clearing, stale revision suppression, and asset reference validation.
Deduplicate in-flight exports within the bounded session cache, retry superseded selections, and reuse same-node vector exports only with complete unchanged geometry and paint context. Keep missing fonts, unsupported geometry, masks, and backdrop-dependent content uncached.

Expand a small authored fixture into 144 variants in memory. Verify pixel-equivalent emission, measure cold and twenty warm replacements with phase traces, and test cache budgets, invalidation, failure, and cancellation. Full pnpm verify passes with 306 unit and 31 browser tests; root pnpm knip and REUSE pass.
Ignore fixture-only copyright metadata when comparing generated design output and require repository autofix, lint and header checks in the plugin guidance.

Validated full CI autofix and lint tasks, explicit header and REUSE 6.2.0 checks, root spelling, pnpm verify (306 unit and 31 browser tests), and root Knip last.
Refresh the plugin's direct dependencies while retaining the repository's shared catalog pins.\n\nChangeLog: Update Figma plugin dependencies.

# Conflicts:
#	pnpm-lock.yaml
#	tools/figma-inspector/package.json
Apply archive identity and channel metadata during packaging. Validate the real nightly archive instead of rebuilding an artificial test package.
Remove the unused behavior option, duplicate template bindings, empty renderer map, unreachable naming branch, and decision cache with no hits. Delete the test-only element shape helper.
…zation

Keep assets required by boolean-bound hidden nodes and their descendants; skip disabled paints. Retain binary bytes for all live captures and codegen. Delete test-only capture and snapshot wrappers, synthetic SVG bounds, and duplicate PNG parsing. Exercise the production capture and validation entry points directly.
Generate specialized preview and reusable native output once each, preserving warnings and rejecting native failures before presentation. Keep one current capture and lazy snapshot recovery; delete export RPC, cross-selection retention, redundant worker state, and obsolete transport formats. Remove hidden UI, demo sources, and timer-based clipboard labels.
The file-specific copyright annotation overrides the general Lucide annotation. Include the MIT license in that entry so REUSE recognizes both icons.
TypeScript and Knip resolve generated interpreter imports in Figma and SlintPad. Depend on the existing build task so clean checkouts generate these files before linting.

Allow twenty minutes for the lint job to include a cold Rust and WASM build.
Describe the generated interpreter modules for type checking and ignore their virtual imports in Knip. Restore the lint job's original dependency graph and timeout so clean lint runs do not compile Slint.
Build the WASM interpreter from the current pre-release/1.18 tip instead of the enclosing workspace. Record and verify that exact revision in packaged provenance.

Keep the generated checkout clean and place build output under the plugin's ignored generated directory.
The shared interpreter aliases are generated only for runtime builds. Ignore them at the root because Knip attributes SlintPad's unresolved alias to the root workspace in a clean checkout.
Git ignore entries are tool and directory names, not prose. Exclude every .gitignore from repository and incremental spell checks.
Use weight and italic variation axes for native typography. Retain captured axes in snapshots and diagnose settings that Slint cannot express.
Capture painted bounds without changing the layout box. Size inner text from Slint preferred dimensions and preserve its alignment inside the original box.

Restrict wrappers to fixed-size plain single-line text. Keep wrapping paragraphs, styled text, truncation and hug sizing unchanged. Route typography variables to the inner Text.

Validate with capture and conversion tests, a pixel-identical Inter regression, and the exported switch frame rendered by slint-viewer.
Use the existing unavailable-font fallback without identifying font brands. Preserve raster capture for Unicode private-use glyphs omitted from the embedded WASM font, including glyphs mixed with ordinary text.
Render eight fixed nested containers through the pinned interpreter without depth recovery. This provides a baseline for narrowing recovery; it does not prove that deeper layouts avoid repeated measurement.
Remove the blanket captured-width override from preview images. Preserve the component image measurement fallback: removing it leaves the pinned interpreter compiling indefinitely in both preview and export reproductions. Cover conditional SVG branches and retain ordinary HUG/FILL layout constraints.
Read family names, glyph mappings, weight axes, and italic availability from the embedded font during the runtime build. Use these capabilities instead of an Inter-only allowlist, and rasterize unavailable styles, axes, or glyphs. Native exports remain editable and retain their font requirements. Font family matching cannot verify the Figma font version.
Use the same finite-domain value selection for State and every other variant axis. Delete state-specific selectors, appearance generation, and tests of that removed machinery. Compare renamed axes and retain public contracts and rendering coverage.
Retain every native layout instead of flattening at a fixed nesting depth. Twenty nested fixed containers render through the pinned interpreter, and the original 56-variant Select family renders in Figma Desktop without recovery diagnostics. Retain the separately reproduced conditional image measurement fallback.
Check in the font capability manifest and verify it against the pinned runtime during the interpreter build. Fresh-checkout type checks and Knip use the manifest without preparing or building WASM. Require an explicit reviewed manifest update when embedded fonts change.
Keep the authored layout box and use runtime text measurement to select between single-line ink expansion and width-preserving wrapped rendering. Grow the rendering box symmetrically in whole pixels to preserve glyph alignment.

Give private measurement items stable identities across component variants and propagate public text and typography bindings to each rendering path. Report the remaining styled, intrinsic-size, justified, and wrapped horizontal-overhang limitations.
Keep captured widths for preview images that hug both axes. Nested Flexbox layouts otherwise measure image heights through layout-assigned widths, creating a binding loop in the pinned Slint runtime. Leave FILL sizing and native project export unchanged.

Cover reusable and specialized nested HUG layouts in the browser and check the rendered image dimensions. Disabling the width constraint reproduces the compiler failure. Verify the complete Button family in Figma, all 333 unit tests and 46 browser tests, repository autofix checks, and license headers.
Delete cross-variant ID normalization. Allocate fresh helper IDs when emitting each output tree, using one counter for the complete generated file, and rewrite references through that tree's identity mapping.

Preserve sibling measurement groups as complete variant alternatives. Check element dependencies before extracting private components. Cover different text metrics in reusable preview and native export; disabling grouping reproduces the compiler failure.
Reconstruct image URLs from the exact packaged bytes for offline compiler validation without changing the portable export. Preserve quoted code examples and verify the asset round trip.
Compile the native export with the pinned runtime before marking a preview successful or exposing Copy and Export. Cache only successful validation, and validate changed exports even when the specialized preview is unchanged.

Cover cold and warm preview failures, disabled output actions, blank source, and recovery after an invalid export. Full verification passes 333 unit tests and 50 browser tests; repository autofix, lint, and license checks pass.
The plugin version follows the monorepo release version independently of the pinned WASM runtime. Compare packaged runtime provenance with runtime-pin.json so a monorepo version bump does not invalidate the package check.
@NigelBreslaw
NigelBreslaw force-pushed the nigel/replace-figma-plugin branch from 9f97c5b to aaa734e Compare September 18, 2026 08:38
Use the shared verified runtime checkout for Cargo metadata and license texts, including an explicit SLINT_REPO override. The enclosing workspace has unrelated dependencies that are not cached by the pinned WASM build.

Cover the checkout paths and verification failure with unit tests. Check the packaged runtime dependency version against runtime-pin.json rather than the monorepo release version.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants