@unmade/text-renderer 0.1.12 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # @unmade/text-renderer
2
+
3
+ Pure function SVG text renderer. No side effects, all dependencies injected explicitly. Web worker compatible.
4
+
5
+ ## Public API
6
+
7
+ ```typescript
8
+ import { getRenderedText } from '@unmade/text-renderer';
9
+
10
+ const svg = await getRenderedText({
11
+ text: 'HELLO',
12
+ fontUrl: 'https://example.com/font.ttf',
13
+ physicalSize: [40, 'mm'],
14
+ boxDimensions: {
15
+ width: 500,
16
+ height: 200,
17
+ physicalWidth: 100,
18
+ physicalHeight: 40,
19
+ physicalUnits: 'mm',
20
+ },
21
+ spacing: { outlineWidth: 0, letterSpacing: 0, letterSpacingOutline: 0 },
22
+ baseline: 'flat', // or 'curved', or { type: 'custom', path: '...' }
23
+ horizontalAlignment: 'centre', // 'left' | 'centre' | 'right' | 'distributed'
24
+ verticalAlignment: 'centre', // 'top' | 'centre' | 'bottom'
25
+ fillColour: { hex: '#000000' },
26
+ });
27
+ ```
28
+
29
+ ### Import paths
30
+
31
+ ```typescript
32
+ import { getRenderedText } from '@unmade/text-renderer'; // Browser
33
+ import { getRenderedText } from '@unmade/text-renderer/node'; // Node.js
34
+ import { getRenderedText } from '@unmade/text-renderer/worker'; // Web Worker
35
+ ```
36
+
37
+ ## Configuration Engine adapter
38
+
39
+ The `ce-adapter` sub-package bridges CE (Configuration Engine) editor state to renderer options:
40
+
41
+ ```typescript
42
+ import { extractTextPlacements, mapStateToRendererOptions } from '@unmade/text-renderer/ce-adapter';
43
+
44
+ const placements = extractTextPlacements(editor); // LoadedTextPlacement[]
45
+ const options = mapStateToRendererOptions(placements[0]); // GetRenderedTextOptions
46
+ const svg = await getRenderedText(options);
47
+ ```
48
+
49
+ `extractTextPlacements` reads an editor instance and returns one `LoadedTextPlacement` per text placement, resolving fonts, colours, and position data from the CE state.
50
+
51
+ `mapStateToRendererOptions` converts a `LoadedTextPlacement` into the `GetRenderedTextOptions` shape that `getRenderedText` accepts — including alignment normalisation (CE uses American English, TR uses British English).
52
+
53
+ ## Comparison system
54
+
55
+ The `packages/tr-comparison` package provides a pipeline for validating TR output against the CE's own rendering for real production designs.
56
+
57
+ ### How it works
58
+
59
+ 1. A design URL is POSTed to the comparison Lambda
60
+ 2. The Lambda loads the design via the CE factory, extracts all text placements, and renders each one with both CE and TR
61
+ 3. Both outputs are rasterised to PNG and diffed pixel-by-pixel with pixelmatch
62
+ 4. Results (match score, images, state) are stored in S3 and indexed in DynamoDB
63
+ 5. A browser comparison is also run via Puppeteer against the deployed demo app
64
+ 6. The comparison dashboard at `packages/tr-comparison/src` displays all results
65
+
66
+ ### Stored S3 artefacts
67
+
68
+ For each placement comparison:
69
+
70
+ ```
71
+ comparisons/{designUrlHash}/{timestamp}/{placementId}/
72
+ ce.png # Config Engine render
73
+ tr.png # Text Renderer render
74
+ diff.png # Pixel difference heatmap
75
+ state.json # LoadedTextPlacement (CE state passed to the adapter)
76
+ renderer-options.json # GetRenderedTextOptions (mapped TR input)
77
+ ```
78
+
79
+ ## Regression tests
80
+
81
+ Regression tests live in `__tests__/regression.test.ts` and use fixture pairs in `__tests__/fixtures/regression/`:
82
+
83
+ | File | Contents |
84
+ |------|----------|
85
+ | `{name}.json` | Fixture metadata + `LoadedTextPlacement` |
86
+ | `{name}.png` | Reference PNG (expected TR render) |
87
+
88
+ The test pipeline for each fixture:
89
+
90
+ ```
91
+ LoadedTextPlacement
92
+ → mapStateToRendererOptions()
93
+ → getRenderedText()
94
+ → SVG → PNG (resvg-js)
95
+ → pixelmatch diff against {name}.png
96
+ → fail if diff > 1%
97
+ ```
98
+
99
+ ### Adding a fixture
100
+
101
+ 1. Run a comparison in the dashboard against a design URL
102
+ 2. Select the record and click **Save as fixture** in the detail panel
103
+ 3. Enter a descriptive name (e.g. `curved-jersey-40mm`) — two files download
104
+ 4. Place both files in `__tests__/fixtures/regression/`
105
+ 5. Run `npm test` to confirm the fixture passes, then commit
106
+
107
+ ### Updating fixtures after an intentional change
108
+
109
+ ```bash
110
+ UPDATE_FIXTURES=true npm test
111
+ ```
112
+
113
+ This re-renders all fixtures and overwrites the stored PNGs. Review the diffs, then commit.
114
+
115
+ > Regression tests require network access to fetch fonts from their CDN URLs.