Skip to content

Commit 2558f05

Browse files
authored
Merge pull request #26 from somnai-dreams/demo/justification-comparison-split
refactor: split justification-comparison into .html + .ts
2 parents 89cd7f6 + b042fac commit 2558f05

2 files changed

Lines changed: 992 additions & 0 deletions

File tree

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta name="description" content="Side-by-side comparison of CSS/greedy, hyphenated, and optimal (Knuth-Plass) justification algorithms — powered by Pretext.">
7+
<title>Justification Algorithms Compared — Pretext Demo</title>
8+
<style>
9+
* { box-sizing: border-box; margin: 0; }
10+
html, body { min-height: 100%; background: #faf8f5; color: #2a2520; overflow-x: auto; }
11+
body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
12+
13+
.page { max-width: 1140px; margin: 0 auto; padding: 32px 24px 80px; overflow: visible; }
14+
15+
h1 {
16+
font: 300 32px/1.2 Georgia, "Times New Roman", serif;
17+
color: #1a1714; letter-spacing: -0.5px; margin-bottom: 8px;
18+
}
19+
.subtitle {
20+
font: 400 13px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif;
21+
color: #8a7f70; margin-bottom: 20px;
22+
}
23+
24+
.controls {
25+
display: flex; align-items: center; gap: 16px;
26+
margin-bottom: 24px; flex-wrap: wrap; justify-content: center;
27+
}
28+
.controls label {
29+
font: 500 11px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
30+
color: #8a7f70; text-transform: uppercase; letter-spacing: 0.5px;
31+
}
32+
.controls input[type="range"] {
33+
width: 220px; accent-color: #5a4f40;
34+
}
35+
.width-val {
36+
font: 600 13px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
37+
color: #5a4f40; min-width: 42px;
38+
}
39+
40+
.columns {
41+
display: flex; gap: 24px; padding-bottom: 16px;
42+
justify-content: center;
43+
}
44+
.column {
45+
flex: 0 0 auto; min-width: 200px;
46+
}
47+
.col-header {
48+
font: 600 11px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
49+
color: #5a4f40; text-transform: uppercase; letter-spacing: 0.8px;
50+
margin-bottom: 4px;
51+
}
52+
.col-desc {
53+
font: 400 11px/1.3 "Helvetica Neue", Helvetica, Arial, sans-serif;
54+
color: #a09888; margin-bottom: 12px;
55+
}
56+
57+
.col-canvas-wrap {
58+
position: relative; border: 1px solid #e8e0d4; border-radius: 3px;
59+
background: #fff; overflow: hidden;
60+
}
61+
.col-canvas-wrap canvas { display: block; }
62+
63+
.css-col {
64+
position: relative;
65+
border: 1px solid #e8e0d4; border-radius: 3px;
66+
background: #fff; overflow: hidden;
67+
}
68+
.css-text {
69+
font: 15px/24px Georgia, "Times New Roman", serif;
70+
text-align: justify;
71+
padding: 12px;
72+
hyphens: none; -webkit-hyphens: none;
73+
word-break: normal; overflow-wrap: break-word;
74+
text-align-last: left;
75+
}
76+
.css-river-overlay {
77+
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
78+
pointer-events: none;
79+
}
80+
81+
.metrics {
82+
margin-top: 8px; padding: 8px 10px;
83+
background: #f5f2ed; border-radius: 3px;
84+
font: 400 11px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
85+
color: #6a6055;
86+
}
87+
.metrics .metric-row { display: flex; justify-content: space-between; }
88+
.metrics .metric-label { color: #8a7f70; }
89+
.metrics .metric-value { font-weight: 600; color: #5a4f40; }
90+
.metrics .metric-value.bad { color: #c44; }
91+
.metrics .metric-value.ok { color: #b87020; }
92+
.metrics .metric-value.good { color: #2a8a4a; }
93+
94+
.col-note {
95+
font: 400 11px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif;
96+
color: #a09888; margin-top: 10px; padding: 0 2px;
97+
}
98+
99+
.topbar {
100+
padding: 12px 16px; text-align: center;
101+
font: 400 11px/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
102+
color: rgba(120,110,95,0.6);
103+
}
104+
.topbar a { color: rgba(100,90,75,0.7); text-decoration: none; border-bottom: 1px solid rgba(100,90,75,0.25); }
105+
.topbar a:hover { color: #555; border-bottom-color: #aaa; }
106+
107+
.footer {
108+
text-align: center; padding: 40px 24px 32px;
109+
font: 400 12px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
110+
color: #b0a898;
111+
}
112+
.footer a {
113+
color: #8a7f70; text-decoration: none;
114+
}
115+
.footer a:hover { text-decoration: underline; }
116+
.footer .sep { margin: 0 8px; }
117+
</style>
118+
</head>
119+
<body>
120+
<div class="topbar">
121+
<div>Built with <em>Pretext</em> by <a href="https://dearlarry.co" target="_blank">Maxwell Ingham</a> &nbsp;&nbsp;&nbsp;&nbsp; <a href="https://github.com/somnai-dreams" target="_blank">GitHub</a> &nbsp;&nbsp;&nbsp;&nbsp; <a href="https://twitter.com/somnai_dreams" target="_blank">Twitter</a></div>
122+
</div>
123+
<div class="page">
124+
<h1 style="text-align:center">Justification Algorithms Compared</h1>
125+
<p class="subtitle" style="text-align:center">The same passage, three approaches. Narrow the column to reveal the differences.</p>
126+
127+
<div class="controls">
128+
<label for="widthSlider">Column width</label>
129+
<input type="range" id="widthSlider" min="200" max="600" value="364">
130+
<span class="width-val" id="widthVal">364px</span>
131+
</div>
132+
133+
<div class="columns" id="columns">
134+
<!-- Column 1: CSS / Greedy -->
135+
<div class="column" id="col0">
136+
<div class="col-header">CSS / Greedy</div>
137+
<div class="col-desc">Native browser justification</div>
138+
<div class="css-col" id="cssCol">
139+
<div class="css-text" id="cssText"></div>
140+
<div class="css-river-overlay" id="cssRiverOverlay"></div>
141+
</div>
142+
<div class="metrics" id="metrics0"></div>
143+
<div class="col-note">CSS and greedy line-breaking produce similar results — both fill each line left-to-right and break when the line overflows. The differences emerge with hyphenation and global optimization.</div>
144+
</div>
145+
146+
<!-- Column 2: Pretext + Hyphenation -->
147+
<div class="column" id="col2">
148+
<div class="col-header">Pretext (Hyphenation)</div>
149+
<div class="col-desc">Greedy with syllable-level hyphenation</div>
150+
<div class="col-canvas-wrap"><canvas id="c2"></canvas></div>
151+
<div class="metrics" id="metrics2"></div>
152+
</div>
153+
154+
<!-- Column 3: Optimal (Knuth-Plass) -->
155+
<div class="column" id="col3">
156+
<div class="col-header">Pretext (Knuth-Plass)</div>
157+
<div class="col-desc">Optimal global line-breaking with syllable hyphenation</div>
158+
<div class="col-canvas-wrap"><canvas id="c3"></canvas></div>
159+
<div class="metrics" id="metrics3"></div>
160+
</div>
161+
</div>
162+
</div>
163+
164+
<footer class="footer">
165+
Built with Pretext<span class="sep">&middot;</span><a href="https://github.com/somnai-dreams" target="_blank">GitHub</a><span class="sep">&middot;</span><a href="https://twitter.com/somnai_dreams" target="_blank">@somnai_dreams</a>
166+
</footer>
167+
168+
<script type="module" src="./justification-comparison.ts"></script>
169+
</body>
170+
</html>

0 commit comments

Comments
 (0)