@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 +115 -0
- package/dist/index.cjs +5 -5
- package/dist/index.js +705 -698
- package/dist/node/index.cjs +5 -5
- package/dist/node/index.js +668 -661
- package/dist/worker/index.cjs +15 -15
- package/dist/worker/index.js +1219 -1212
- package/package.json +5 -1
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.
|