feat(pipeline): InDesign IR to WordPress design token mapper (#64)#91
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.jsonpartial — additive, namespaced, deep-merges into a base theme.design-tokens.json— DTCG / Style Dictionary v4 compatible.A
bin/map-tokens.mjsCLI composes with the parser CLIs (or parses.idml/.pdfdirectly).Design decisions
Captured in
docs/plans/2026-05-29-indesign-token-mapper-design.md:Colorwith optional rawcomponentsand convertCMYK/LAB → sRGB in a shared module with out-of-gamut warnings. Side benefit:
LAB/Spot swatches no longer collapse to
#000000in the IR.merge by slug), so derived tokens never clobber the curated base.
and a zod schema for the emitted subset.
else namespaced derived slugs.
How it maps
color.palette(re-derive sRGB from components, dedupe by hex within tolerance, reuse close base slugs).typography.fontSizes(clustered) +styles.elements(h1–h6, caption) andstyles.blocks['core/paragraph']for body.typography.fontFamiliesviaconfig/font-map.json(heuristic generic fallback + warning when unmapped).spacing.spacingSizes.Acceptance criteria
Test plan
pnpm --filter @flavian/pipeline test→ 88/88 pass (was 67 before this PR; existing parser/round-trip tests still green).color,ir-color,parser-color-components,map-colors,map-typography,map-spacing,map-fonts,map-theme-json,map-design-tokens,map-tokens(e2e).--out-dir.Notes
Color.componentsoptional);irVersionstays1, and existing IRs still validate. The two merged parsers were routed through the new sharedcolor.js.malformed.test.mjscase usedLABas 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