Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4d204dd
Add figma transformer package scaffold
chubes4 Jun 22, 2026
a4fe3f7
Add fig-kiwi archive parsing diagnostics
chubes4 Jun 22, 2026
80456bd
Add Figma scenegraph normalization primitives
chubes4 Jun 22, 2026
8350d07
Improve figma static HTML emitter
chubes4 Jun 22, 2026
5e09edb
Add figma decoder payload handoff
chubes4 Jun 22, 2026
f44b58d
Add Figma layout IR emission
chubes4 Jun 22, 2026
0ed1d83
Improve Figma text and paint normalization
chubes4 Jun 22, 2026
0915063
Improve Figma asset and vector handling
chubes4 Jun 22, 2026
77de71c
Strengthen figma transformer parity contract
chubes4 Jun 22, 2026
c594c57
Fix figma transformer integration assertions
chubes4 Jun 22, 2026
101f934
Add fig kiwi binary envelope metadata
chubes4 Jun 22, 2026
e3232ce
Strengthen fig zstd runtime diagnostics
chubes4 Jun 22, 2026
de1a006
Improve Figma layout CSS emission
chubes4 Jun 22, 2026
5724cff
Emit supported figma vectors as SVG
chubes4 Jun 22, 2026
5adbe25
Add Figma component instance IR foundation
chubes4 Jun 22, 2026
a27ef5a
Extend figma parity artifact reporting
chubes4 Jun 22, 2026
8b91ef2
Document figma transformer local fixture workflow
chubes4 Jun 22, 2026
3ad5b98
Import fig kiwi node changes end to end
chubes4 Jun 22, 2026
95d603b
Add optional zstd decoder adapters
chubes4 Jun 22, 2026
34af69b
Improve decoded fig import handoff
chubes4 Jun 22, 2026
4f56d2d
Add synthetic fig kiwi decoder harness
chubes4 Jun 22, 2026
824759c
Tighten fig kiwi schema detection
chubes4 Jun 22, 2026
2dd5711
Require zstd for fig imports
chubes4 Jun 22, 2026
b400093
Improve Figma transform fidelity
chubes4 Jun 23, 2026
b34c9ea
Allow larger website artifact images
chubes4 Jun 23, 2026
608c4c7
Preserve Figma graphic wrappers
chubes4 Jun 23, 2026
065d3b8
Keep HTML wrapper contract generic
chubes4 Jun 23, 2026
cd902b4
Preserve safe inline SVG icons
chubes4 Jun 23, 2026
6bd4424
Resolve Figma vector instance geometry
chubes4 Jun 23, 2026
d5cfac8
Improve Figma text glyph attribution
chubes4 Jun 23, 2026
193c86b
Merge remote-tracking branch 'origin/trunk' into feature/figma-transf…
chubes4 Jun 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Blocks Engine is a collection of tools for generating, transforming, and materia
## Packages

- [`php-transformer`](php-transformer/) - PHP primitives for converting HTML, Markdown, and generated website artifacts into WordPress-native block outputs.
- [`figma-transformer`](figma-transformer/) - PHP primitives for converting Figma `.fig` archives and Figma-derived scenegraphs into static HTML website artifacts with parity diagnostics.
58 changes: 58 additions & 0 deletions docs/contracts/figma-transformer-result.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Figma Transformer Result Contract

`figma-transformer` returns `blocks-engine/figma-transformer/result/v1` envelopes.

The contract is intentionally static-HTML-first. Downstream products can pass generated HTML to `php-transformer`, Static Site Importer, Studio, or any other materialization layer.

The package boundary is:

```text
.fig file or decoded scenegraph
-> normalized Figma IR
-> static HTML/CSS/assets artifact
-> php-transformer handles WordPress block conversion later
```

Required top-level fields:

- `schema`: `blocks-engine/figma-transformer/result/v1`
- `status`: `success`, `success_with_warnings`, or `failed`
- `diagnostics`: stable diagnostic records
- `files`: generated artifact files such as `index.html` and `style.css`
- `assets`: generated or extracted assets
- `source_reports.figma`: Figma intake, scenegraph, and provenance reports
- `parity`: `blocks-engine/figma-transformer/parity-report/v1`
- `metrics`: package-level transform metrics

## Parity Report

The parity report records source screenshot evidence, generated HTML screenshot evidence, side-by-side output, diff output, diff summaries, artifact paths, and runner-supplied metrics. Browser-heavy parity runners should persist artifacts through Homeboy or another reviewable artifact surface.

Required parity fields:

- `schema`: `blocks-engine/figma-transformer/parity-report/v1`
- `status`: `not_run`, `pending`, or `compared`
- `reason`: stable runner-readable reason string when useful
- `artifacts`: paths or URLs for report-level artifacts supplied by the caller
- `source`: source-design evidence such as screenshot path, viewport, frame ID, or capture metadata
- `generated`: generated HTML evidence such as screenshot path, viewport, URL, or capture metadata
- `side_by_side`: optional side-by-side artifact metadata
- `diff`: optional visual diff artifact metadata
- `diff_summary`: optional compact diff summary such as changed pixels, threshold, or ratio
- `metrics`: optional runner metrics

Status meanings:

- `not_run`: no parity runner has executed for this transform.
- `pending`: parity work is queued, external, or otherwise incomplete.
- `compared`: caller-supplied evidence describes a completed source-vs-generated comparison.

## `.fig` Decoder Limits

Arbitrary `.fig` files are not fully decoded by the PHP-native package yet. Current `.fig` support safely opens `.fig` files or wrapper ZIPs, identifies nested `.fig` entries, reports `fig-kiwi` prelude/version/chunk metadata, inventories embedded files/assets, and records compression diagnostics.

Next decoder milestones are schema chunk parsing, Zstandard message decoding when supported by the runtime, mapping decoded Kiwi messages into normalized IR, and expanding layout/paint/text/component/asset coverage against external real-file evidence.

## Fixture Strategy

Repository tests should use small synthetic fixtures for contract shape, deterministic output, and decoder safety. Large real `.fig` files should stay out of git. Real-design parity evidence should be generated externally, usually through Homeboy, and attached to the relevant issue or PR as reviewable artifacts.
217 changes: 217 additions & 0 deletions figma-transformer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# Figma Transformer

Figma Transformer is a PHP primitive for converting Figma designs into static HTML website artifacts.

This package is intentionally WordPress-native and product-neutral. It owns Figma intake, scenegraph normalization, static HTML artifact generation, and visual-parity report contracts. It does not own WordPress page creation, block conversion, theme activation, Studio orchestration, or Static Site Importer UI.

## Package Contract

The package contract is:

```text
.fig file or decoded scenegraph
-> normalized Figma IR
-> static HTML/CSS/assets artifact
-> php-transformer converts static artifacts to WordPress blocks later
```

`figma-transformer` stops at static website artifacts. WordPress block materialization remains a downstream `php-transformer` responsibility so Figma intake, HTML parity, and WordPress block conversion can evolve independently.

## Boundary

Figma Transformer owns reusable transformation primitives:

- `.fig` archive intake and safety diagnostics.
- Figma `fig-kiwi` archive metadata parsing.
- Figma scenegraph normalization.
- Static HTML, CSS, and asset artifact generation.
- Figma-vs-HTML visual parity report contracts.
- Generic provenance metadata that lets callers trace HTML back to Figma nodes.

Figma Transformer does not convert HTML into WordPress blocks. Use `php-transformer` for HTML, Markdown, and website artifact conversion into WordPress-native block outputs.

## Public API Surface

Consumers should treat these classes and helper functions as the public entrypoints for the current package:

- `FigmaTransformer` - transforms `.fig` files or normalized scenegraph arrays into static HTML result envelopes.
- `Contract\FigmaTransformResult` - stable result envelope for process, HTTP, fixture, and compatibility boundaries.
- `FigFile\FigArchiveReader` - reads safe `.fig` archive metadata and embedded asset manifests.
- `Html\StaticHtmlEmitter` - emits deterministic static HTML artifact files from a normalized scenegraph.
- `Parity\ParityReportBuilder` - builds the parity report envelope from source/generated screenshot evidence and metrics supplied by the caller.

## WordPress Plugin Usage

Install or symlink the `figma-transformer/` directory into `wp-content/plugins/blocks-engine-figma-transformer/`, run Composer when available, and activate **Blocks Engine Figma Transformer**.

```php
$result = blocks_engine_figma_transformer_transform_file('/path/to/design.fig', array(
'source' => 'upload:design.fig',
));
```

Available plugin helpers:

- `blocks_engine_figma_transformer_version()`
- `blocks_engine_figma_transformer_path()`
- `blocks_engine_figma_transformer_transform_file()`
- `blocks_engine_figma_transformer_transform_scenegraph()`

## Current Draft Status

This package currently scaffolds the public API and `.fig` intake contract. Full pure-PHP Kiwi message decoding, source screenshot rendering, and browser-backed visual parity scoring are planned behind the contracts introduced here.

The first target fixture is a local `.fig_.zip` export containing `Fisiostetic.fig`, whose inner `canvas.fig` starts with `fig-kiwi` and uses a raw-deflate schema chunk plus a Zstandard-compressed message chunk.

### Current `.fig` Support Limits

Arbitrary `.fig` files are not fully decoded today. The current file path is an intake and diagnostics layer that safely opens `.fig` or wrapper ZIP files, identifies nested `.fig` entries, reports `fig-kiwi` metadata, inventories embedded files/assets, and records compression capabilities. It does not yet reconstruct a complete Figma scenegraph from production Kiwi payloads.

Next decoder milestones:

- Parse the raw-deflate schema chunk into a useful schema model.
- Decode Zstandard message chunks when the PHP runtime has a supported Zstandard capability.
- Map decoded Kiwi messages into the normalized IR already accepted by `transformScenegraph()`.
- Expand layout, paint, text, component, and asset coverage against external real-file evidence.

### Zstandard Support

Zstandard decoding is required for direct imports of modern `.fig` files because Figma stores the main Kiwi message chunk as zstd-compressed data. The Composer package requires `ext-zstd` for normal installs.

Supported decoder paths:

- `ext-zstd` with `zstd_uncompress()` available.
- An explicit `Compression\ZstdCapability` adapter callable for operator/local verification when the host provides a trusted decoder through another boundary.
- A WordPress filter adapter registered on `blocks_engine_figma_transformer_zstd_decoder` for environments that intentionally provide decoding outside the extension.
- The CLI-only `--zstd-command=/path/to/zstd` option for local operator checks. This is not used implicitly by the library or plugin runtime.

Adapter callables receive the compressed payload and context array, and return decoded bytes or an array with `data` and optional `diagnostics`:

```php
$zstd = new Automattic\BlocksEngine\FigmaTransformer\Compression\ZstdCapability(
static function (string $payload, array $context): string|false {
return my_zstd_decode($payload);
}
);
```

```php
add_filter(
'blocks_engine_figma_transformer_zstd_decoder',
static fn () => static fn (string $payload, array $context): string|false => my_zstd_decode($payload)
);
```

No pure-PHP Zstandard decoder is bundled today. Unsupported runtimes report `figma_transformer_zstd_extension_missing` or adapter failure diagnostics and continue parsing the rest of the archive metadata.

## Output Contract

Successful transforms produce a static website artifact:

```text
artifact/
index.html
style.css
assets/
parity-report.json
```

The result envelope includes:

- `schema: "blocks-engine/figma-transformer/result/v1"`
- `status`
- `diagnostics[]`
- `files[]`
- `assets[]`
- `source_reports.figma`
- `parity`
- `metrics`

## Parity Contract

Visual parity is measured outside the WordPress import path. The package records source and generated screenshot evidence, side-by-side comparisons, diff images, diff summaries, artifact paths, and metrics supplied by the parity runner. Homeboy or another external browser-backed runner is expected to produce screenshots and image diffs, then pass artifact metadata into this package. WordPress-only consumers can read and display the parity report without running a browser.

Parity report statuses:

- `not_run`: no parity runner has executed for this transform.
- `pending`: parity work is queued, external, or otherwise incomplete.
- `compared`: caller-supplied source/generated evidence and diff data describe a completed comparison.
- `pass`: caller-supplied diff data is within the supplied threshold.
- `fail`: caller-supplied diff data exceeds the supplied threshold.

Parity runners can attach evidence through the `parity` transform option or the CLI metadata flags. The contract accepts source screenshot URL/path metadata, generated screenshot artifact metadata, diff image artifact metadata, pixel mismatch count/ratio, threshold, viewport, and frame id. The transformer stores those references; it does not fetch, render, compare, or commit screenshot files.

```php
$result = blocks_engine_figma_transformer_transform_scenegraph($scenegraph, array(
'frame_id' => '1:1',
'parity' => array(
'status' => 'pass',
'frame_id' => '1:1',
'source_screenshot_url' => 'https://artifacts.example.test/source.png',
'generated_screenshot_artifact' => 'homeboy://runs/123/generated.png',
'diff_image_artifact' => 'homeboy://runs/123/diff.png',
'pixel_mismatch_count' => 10,
'pixel_mismatch_ratio' => 0.005,
'threshold' => 0.01,
'viewport' => array(
'width' => 1200,
'height' => 800,
),
),
));
```

```sh
figma-transformer scenegraph.json \
--frame-id=1:1 \
--parity-status=pass \
--parity-source-screenshot-url=https://artifacts.example.test/source.png \
--parity-generated-screenshot-artifact=homeboy://runs/123/generated.png \
--parity-diff-image-artifact=homeboy://runs/123/diff.png \
--parity-pixel-mismatch-count=10 \
--parity-pixel-mismatch-ratio=0.005 \
--parity-threshold=0.01 \
--parity-viewport=1200x800
```

Homeboy/external runner workflow:

1. Run the Figma transform and persist the static HTML/CSS/assets output.
2. Render the original design and generated artifact in an external browser-backed runner.
3. Upload screenshots, diff images, and any machine-readable diff report to a reviewable artifact surface attached to the issue, PR, or runner record.
4. Re-run or wrap the transform with the parity metadata above so `parity-report.json` contains stable artifact references and numeric comparison results.
5. Link the PR or issue to the external artifact record rather than local paths or localhost URLs.

## Fixture Strategy

Contract tests use small synthetic fixtures that exercise the public envelope, archive safety, deterministic HTML/CSS output, and parity report shape. Large real `.fig` exports are not committed to the repository. When real-file parity evidence is needed, generate it externally through Homeboy or another reviewable artifact surface and attach the resulting reports/screenshots to the relevant issue or PR.

### Local Real-File Checks

Use real `.fig` files only as operator-owned, non-committed inputs. Good manual sources are designs you own, Figma Community files or templates that allow duplication/export, and files accessible through the Figma REST API.

Recommended local layout:

```text
~/Downloads/figma-transformer-fixtures/
source.fig
source-api.json
evidence/
```

Example CLI checks:

```sh
mkdir -p "$HOME/Downloads/figma-transformer-fixtures/evidence"
php figma-transformer/bin/figma-transformer "$HOME/Downloads/figma-transformer-fixtures/source.fig" > "$HOME/Downloads/figma-transformer-fixtures/evidence/source-result.json"
php figma-transformer/bin/figma-transformer "$HOME/Downloads/figma-transformer-fixtures/source-api.json" > "$HOME/Downloads/figma-transformer-fixtures/evidence/source-api-result.json"
```

Evidence to keep with the issue or PR:

- The original Figma URL and file key, not the `.fig` file.
- Whether the input came from **File > Save local copy**, a Community duplicate, or `GET /v1/files/:key`.
- The result envelope JSON, diagnostics, generated artifact manifest, and parity screenshots/diffs when a parity runner was used.
- Runtime details that affect diagnostics, especially PHP version, `ZipArchive`, and Zstandard support.

Do not copy real `.fig` exports, downloaded image fills, rendered screenshots, or proprietary customer designs into repository fixtures. If a real file exposes a decoder gap, reduce it to a synthetic fixture or attach non-sensitive evidence through the relevant issue/PR artifact workflow.
Loading
Loading