1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Phase 5 line-breaking: [`BreakStrategy`] switches
//! [`crate::layout::layout_paragraph`] between the greedy word-wrap packer
//! (`crate::layout::greedy`, Phase 1/2) and [`knuth_plass`]'s total-fit
//! demerits-minimizing dynamic-programming breaker; [`Hyphenation`] opts a
//! paragraph into [`hyphenate`]'s real hyph-utf8-derived discretionary
//! hyphen points (via the [`hypher`] crate — Typst's own hyphenator).
//!
//! [`Hyphenation`] is consulted **only** by [`BreakStrategy::KnuthPlass`] —
//! Phase 1/2's greedy packer (`crate::layout::greedy::pack_lines`) is
//! unchanged and never reads a word atom's hyphenation opportunities, so
//! `Greedy` (the still-default strategy) stays byte-identical to every
//! prior phase's output regardless of what `Hyphenation` a caller sets (see
//! this crate's `CLAUDE.md` Phase 5 section, and its typography-wave
//! section, for the full rationale).
pub
pub use Lang;
/// Which line-breaking algorithm [`crate::layout::layout_paragraph`] uses to
/// decide where a [`crate::model::Paragraph`]'s lines end.
/// Hyphenation strategy for a [`crate::model::Paragraph`].
///
/// Only consulted by [`BreakStrategy::KnuthPlass`] (see this module's own
/// doc comment). Backed by [`hyphenate`]'s real hyph-utf8-derived pattern
/// automata (the [`hypher`] crate, Typst's own hyphenator — see this
/// crate's `CLAUDE.md` typography-wave section for the hard-cutover
/// rationale, superseding the earlier hand-rolled ~20-pattern English-only
/// Liang engine).
/// Line-breaking tuning knobs (typography track T5, 2026-07-25) — every
/// constant [`knuth_plass`]'s own DP + [`hyphenate`]'s own minimums used to
/// hardcode, exposed through [`crate::model::Paragraph::line_break_params`]/
/// `with_line_break_params` — the same builder surface the hyphenation
/// LANGUAGE already used (this enum's own `Lang(..)` escape hatch), closing
/// the inconsistency this task's own brief names directly.
///
/// [`Default`] reproduces every one of today's hardcoded values EXACTLY —
/// this crate's own doctrine (`CLAUDE.md`'s "never change rendered output
/// silently"): a debatable default becomes an option whose default
/// preserves today's behavior. Every caller that never touches
/// `line_break_params` gets byte-for-byte identical output to before this
/// wave (see `linebreak::knuth_plass`'s own
/// `default_line_break_params_reproduce_the_hardcoded_constants_exactly`
/// test).
///
/// **No `\tolerance`/`\looseness` field** — [`knuth_plass`]'s own module doc
/// already states this DP is deliberately simplified relative to real TeX
/// ("no looseness passes, no TeX fitness-class tiering... a single-pass DP
/// over feasible breakpoints"): there is no multi-pass looseness-retry loop
/// or fitness-class tiering anywhere in this implementation for such a
/// field to plumb into. Adding an inert `tolerance: f64` nothing reads
/// would be exactly the "field nothing reads" anti-pattern this workspace's
/// own conventions forbid (see this crate's `CLAUDE.md`, e.g. the Phase 2
/// `BreakStrategy` divergence note making the identical call the other
/// direction). If a future pass adds real looseness/fitness-class support,
/// its own knob belongs on `LineBreakParams` then, not as a placeholder now.