Skip to content

feat(pipeline): InDesign IR to WordPress design token mapper (#64)#91

Merged
PAMulligan merged 14 commits into
mainfrom
64-indesign-pipeline-style-and-design-token-mapper-paragraphcharacter-styles-swatches-themejson
May 29, 2026
Merged

feat(pipeline): InDesign IR to WordPress design token mapper (#64)#91
PAMulligan merged 14 commits into
mainfrom
64-indesign-pipeline-style-and-design-token-mapper-paragraphcharacter-styles-swatches-themejson

Conversation

@PAMulligan
Copy link
Copy Markdown
Collaborator

Summary

Stage 3 of the InDesign-to-WordPress pipeline (sub-issue of #61): map the
InDesign IR — produced by either the IDML parser (#62) or the PDF fallback
parser (#63) — to WordPress design tokens, so generated patterns inherit a
coherent design system instead of inline magic numbers.

mapTokens(ir, options) produces three artifacts:

  • theme.json partial — additive, namespaced, deep-merges into a base theme.
  • design-tokens.json — DTCG / Style Dictionary v4 compatible.
  • report — warnings, validation result, provenance, font fallbacks, Google fonts.

A bin/map-tokens.mjs CLI composes with the parser CLIs (or parses .idml/.pdf directly).

Design decisions

Captured in docs/plans/2026-05-29-indesign-token-mapper-design.md:

  1. Color: extend the IR Color with optional raw components and convert
    CMYK/LAB → sRGB in a shared module with out-of-gamut warnings. Side benefit:
    LAB/Spot swatches no longer collapse to #000000 in the IR.
  2. Merge: additive, namespaced partial + a deep-merge helper (token arrays
    merge by slug), so derived tokens never clobber the curated base.
  3. Validation: ajv against the vendored official WordPress theme.json schema
    and a zod schema for the emitted subset.
  4. Typography: dynamic clustered scale that reuses base slugs when close,
    else namespaced derived slugs.

How it maps

  • Swatches → color.palette (re-derive sRGB from components, dedupe by hex within tolerance, reuse close base slugs).
  • Paragraph styles → typography.fontSizes (clustered) + styles.elements (h1–h6, caption) and styles.blocks['core/paragraph'] for body.
  • Fonts → typography.fontFamilies via config/font-map.json (heuristic generic fallback + warning when unmapped).
  • Page margins / gutters / paragraph spacing → quantized spacing.spacingSizes.

Acceptance criteria

  • Generated theme.json validates against the WordPress block theme schema (ajv + vendored schema).
  • Palette includes all distinct swatches, deduped by hex within a configurable tolerance.
  • Every typography scale entry is referenced by ≥1 paragraph style (provenance recorded in the report).
  • Font fallback warnings are emitted and listed in the generator report.
  • Tests cover CMYK→sRGB (and LAB→sRGB) against fixtures, paragraph-style clustering, and the merge-with-base path.
  • Works on either IR — end-to-end test runs on both an IDML-built and a PDF-built IR.

Test plan

  • pnpm --filter @flavian/pipeline test88/88 pass (was 67 before this PR; existing parser/round-trip tests still green).
  • New suites: color, ir-color, parser-color-components, map-colors, map-typography, map-spacing, map-fonts, map-theme-json, map-design-tokens, map-tokens (e2e).
  • CLI verified manually: partial → stdout, report summary → stderr, four artifacts → --out-dir.

Notes

  • The IR change is additive (Color.components optional); irVersion stays 1, and existing IRs still validate. The two merged parsers were routed through the new shared color.js.
  • One pre-existing malformed.test.mjs case used LAB as its "unknown space" example expecting black; it was repointed to a genuinely unsupported space, with a new test documenting that LAB now converts.

Closes #64.

🤖 Generated with Claude Code

Paul Mulligan and others added 14 commits May 29, 2026 10:29
Add the validated design and a task-by-task TDD implementation plan for
mapping the InDesign IR to WordPress design tokens: a theme.json partial,
a DTCG design-tokens.json, and a generator report. Captures the four
approved decisions: additive IR color components, namespaced partial plus
deep-merge, ajv+zod schema validation, and a dynamic clustered typography
scale.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…apper

Vendor the published WordPress block-theme JSON Schema (draft-07, from
https://schemas.wp.org/trunk/theme.json) and add ajv + ajv-formats so the
mapper can validate generated theme.json output against the official schema.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lets the token mapper convert CMYK/LAB swatches to sRGB with documented
math instead of relying on the parser's naive preview hex. Additive and
optional, so existing IRs still validate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sion

Single source of truth for color math. Adds documented source-space to sRGB
conversion for the mapper: naive profile-free CMYK (0..100), full CIELAB to
sRGB via a D50 connection space with Bradford adaptation and out-of-gamut
detection, plus a colorFromComponents dispatcher that falls back to the
parse-time hex. Device-shaped helpers (rgbToHex/grayToHex/cmykToHex/
nearestSwatch) are retained for the PDF operator path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ersion

Route both parsers through the shared color module. The IDML graphic parser
now attaches raw components and converts LAB swatches to real sRGB colors
instead of collapsing them to black, emitting a color-out-of-gamut warning
when a LAB color exceeds the sRGB gamut. The PDF extractor captures the raw
fill color so synthesized swatches carry components too. pdf/color.js now
re-exports the device helpers from the shared module.

Updates the malformed-input test that used LAB as its unknown-space example
to a genuinely unsupported space, and adds a test documenting LAB conversion.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-derive sRGB from raw components, dedupe by hex within a configurable
tolerance, reuse close base palette slugs, and emit namespaced derived
tokens otherwise. Warns on out-of-gamut and opaque (Spot/Unknown) swatches.
Adds a shared slug helper used across the mapper's token builders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… scale

Cluster near-equal paragraph font sizes into scale entries, reusing close
base font-size slugs or emitting namespaced derived tokens named after the
InDesign style. Every emitted entry is referenced by a style. Recognized
style names (Heading N / Body / Caption) produce element presets with line
height, letter spacing, and text color, with a fallback that binds the
most-used size to the body paragraph.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collect candidate spacings from page margins, inter-frame gutters, and
paragraph space-before/after, quantize to a configurable grid (default 4px),
dedupe, and cap. Emits namespaced spacingSizes and warns that the scale is
approximate for PDF-derived IRs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add config/font-map.json (system + Google families) and map IR fonts to
theme.json fontFamilies. Mapped families reuse a base slug only on exact
stack match, else become namespaced derived families; unmapped families fall
back to a heuristic generic and raise a font-fallback warning. Google fonts
are returned separately for the downstream generator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
assemblePartial builds an additive, namespaced partial; mergeThemeJson folds
it into a base theme with token arrays merged by slug (derived tokens extend
the curated base without clobbering). validateThemeJson checks output against
the vendored official WordPress schema via ajv plus a zod subset schema that
guards the emitted token shapes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Convert the mapped token groups to DTCG format ($value/$type/$description),
read natively by Style Dictionary v4. Description carries the InDesign swatch
or style name as provenance; empty groups are omitted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…and report

Compose the mapper sub-modules into mapTokens(ir, options) -> { partial,
designTokens, merged, report }, source-agnostic across IDML and PDF IRs.
Element presets gain a font family from the style's font, and the body
paragraph is emitted as styles.blocks['core/paragraph'] (theme.json has no
<p> element). Adds the report aggregator and an end-to-end test proving the
mapper runs on both an IDML-built and a PDF-built IR with schema-valid output.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Map an IR (JSON on a path/stdin, or an .idml/.pdf parsed directly) to design
tokens. Prints the theme.json partial on stdout and a report summary on
stderr; --out-dir writes theme.partial.json, theme.merged.json,
design-tokens.json, and report.json. Exit code reflects schema validity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add docs/pipeline/indesign-token-mapper.md (conversion math, font-map format,
warning codes, merge semantics, acceptance-criteria mapping) and update the
pipeline README with the mapper stage, the new module layout, and CLI usage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@PAMulligan PAMulligan self-assigned this May 29, 2026
@PAMulligan PAMulligan added pipeline Figma/Canva-to-WordPress conversion pipeline performance Performance improvements labels May 29, 2026
@PAMulligan PAMulligan moved this from Todo to In Progress in PMDS Open Source Roadmap May 29, 2026
@PAMulligan PAMulligan added this to the v2.0.0 milestone May 29, 2026
@PAMulligan PAMulligan merged commit b1fe980 into main May 29, 2026
4 checks passed
@PAMulligan PAMulligan deleted the 64-indesign-pipeline-style-and-design-token-mapper-paragraphcharacter-styles-swatches-themejson branch May 29, 2026 20:18
@github-project-automation github-project-automation Bot moved this from In Progress to Done in PMDS Open Source Roadmap May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance Performance improvements pipeline Figma/Canva-to-WordPress conversion pipeline

Projects

Development

Successfully merging this pull request may close these issues.

[InDesign pipeline] Style and design-token mapper (paragraph/character styles + swatches → theme.json)

1 participant