giles
1eadefd0c1
Step 17b: Pretext — DOM-free text layout with otfm font measurement
Pure SX text layout library with one IO boundary (text-measure perform).
Knuth-Plass optimal line breaking, Liang's hyphenation, position calculation.
Library (lib/text-layout.sx):
- break-lines: Knuth-Plass DP over word widths
- break-lines-greedy: simple word-wrap for comparison
- hyphenate-word: Liang's trie algorithm
- position-line/position-lines: running x/y sums
- measure-text: single perform (text-measure IO)
Server font measurement (otfm):
- Reads OpenType cmap + hmtx tables from .ttf files
- DejaVu Serif/Sans bundled in shared/static/fonts/
- _cek_io_resolver hook: perform works inside aser/eval_expr
- JIT VM suspension inline resolution for IO in compiled code
~font component (shared/sx/templates/font.sx):
- Works like ~tw: emits @font-face CSS via cssx scope
- Sets font-family on parent via spread
- Deduplicates font declarations
Infrastructure fixes:
- stdin load command: per-expression error handling (was aborting on first error)
- cek_run IO hook: _cek_io_resolver in sx_types.ml
- JIT VmSuspended: inline IO resolution when resolver installed
- ListRef handling in IO resolver (perform creates ListRef, not List)
Demo page at /sx/(applications.(pretext)):
- Hero: justified paragraph with otfm-measured proportional widths
- Greedy vs Knuth-Plass side-by-side comparison
- Badness scoring visualization
- Hyphenation syllable decomposition
25 new tests (spec/tests/test-text-layout.sx), 3201/3201 passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:13:00 +00:00
..
2026-03-24 14:32:55 +00:00
2026-04-12 15:13:00 +00:00
2026-03-24 17:23:09 +00:00
2026-03-24 14:32:55 +00:00
2026-03-24 16:14:40 +00:00
2026-03-14 10:11:48 +00:00
2026-03-12 23:54:38 +00:00
2026-03-08 00:00:23 +00:00
2026-03-24 16:14:40 +00:00
2026-03-11 09:42:04 +00:00
2026-03-24 16:14:40 +00:00
2026-04-04 17:11:12 +00:00
2026-03-02 19:57:27 +00:00
2026-03-24 16:14:40 +00:00
2026-03-25 16:27:33 +00:00
2026-03-07 19:02:29 +00:00
2026-03-31 07:36:36 +00:00
2026-03-25 15:14:10 +00:00
2026-03-12 22:00:12 +00:00
2026-03-28 15:18:45 +00:00
2026-03-24 16:14:40 +00:00
2026-03-02 00:50:57 +00:00
2026-03-06 01:45:29 +00:00
2026-03-18 17:22:51 +00:00
2026-03-08 00:00:23 +00:00
2026-03-24 16:14:40 +00:00
2026-03-24 16:14:40 +00:00
2026-03-24 17:23:09 +00:00
2026-03-11 04:53:34 +00:00
2026-03-24 14:32:55 +00:00
2026-03-14 10:11:48 +00:00