Skip to content

Commit 0280322

Browse files
committed
Add sample for 'title-case' using Paged JS
1 parent 047d14b commit 0280322

8 files changed

Lines changed: 143 additions & 7 deletions

File tree

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ data/*.aux
77
data/*/*-aux
88
data/*.log
99
data/*-aux.json
10+
data/decasify.js
1011
.fonts
1112
static
1213
public

‎Makefile‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ all-system-fonts.css: $(FONTCONFIG_FILE)
156156
%-pagedjs.pdf %-pagedjs.toml: %/pagedjs.html
157157
$(call make_manifest,$(PAGEDJS) $(TYPESETTER_ARGS) $(PAGEDJS_ARGS))
158158

159+
data/title-case-pagedjs.pdf: data/decasify.js
160+
159161
%-satysfi.pdf %-saty.toml: %/satysfi.saty
160162
$(call make_manifest,$(SATYSFI) $(SATYSFI_ARGS))
161163

@@ -181,8 +183,11 @@ static/%.css: sass/%.scss | node_modules
181183
%.avif: %.pdf
182184
$(MAGICK) -density 150 $< $@
183185

184-
static/codemirror.js: src/codemirror.js build.js | node_modules
185-
$(NPX) node build.js
186+
data/decasify.js: src/decasify-bundle.js
187+
static/codemirror.js: src/codemirror.js
188+
189+
data/decasify.js static/codemirror.js: build.js | node_modules
190+
$(NPX) node $<
186191

187192
.PHONY: static
188193
static: $(PDFS) $(PREVIEWS) static/main.css static/codemirror.js

‎build.js‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { build } from "esbuild";
2+
import { readFileSync, writeFileSync } from "fs";
23
import { wasmLoader } from 'esbuild-plugin-wasm'
34

45
await build({
@@ -18,3 +19,46 @@ await build({
1819
'top-level-await': true,
1920
},
2021
});
22+
23+
await build({
24+
entryPoints: ["src/decasify-bundle.js"],
25+
bundle: true,
26+
format: "esm",
27+
target: ["es2020"],
28+
sourcemap: false,
29+
outdir: "data",
30+
outbase: "src",
31+
entryNames: "decasify",
32+
plugins: [wasmLoader({ mode: 'embedded' })],
33+
supported: {
34+
'top-level-await': true,
35+
},
36+
});
37+
38+
/* The following monkey business is LLM generated rubbish. I don't know enough about the internals
39+
* here to do better, but the only utility needed here is some way to trigger our custom sample
40+
* generator code at some point after the decasify WASM library is loaded and before Paged JS starts
41+
* doing layout. I'd love to see a contribution from somebody that does this some saner way.
42+
*/
43+
const src = readFileSync("data/decasify.js", "utf8");
44+
const patched = src
45+
.replace(
46+
/async function loadWasm[\s\S]*?^}/m,
47+
""
48+
)
49+
.replace(/var \{ instance, module \} = await loadWasm\(decasify_bg_default, imports\);/, "var { instance } = await WebAssembly.instantiate(decasify_bg_default, imports);")
50+
.replace(/^export \{.*\};?\n?/m, "");
51+
writeFileSync("data/decasify.js",
52+
"(async function() {\n" +
53+
patched +
54+
"\nwindow.externalLibs._resolveDecasifyReady();\n" +
55+
"\nvar DecasifyHandler = class extends Paged.Handler {\n" +
56+
" constructor(chunker, polisher, caller) { super(chunker, polisher, caller); }\n" +
57+
" async beforeParsed(content) {\n" +
58+
" await window.externalLibs.decasifyReady;\n" +
59+
" window.generateSample(content);\n" +
60+
" }\n" +
61+
"};\n" +
62+
"Paged.registerHandlers(DecasifyHandler);\n" +
63+
"})();\n"
64+
);

‎content/title-case.md‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
title = "Title Case"
33
description = "Title casing prose is more complex than munging some glyphs."
44
weight = 4
5-
extra.typesetters = [ "sile", "typst", "glu" ]
5+
extra.typesetters = [ "sile", "typst", "glu", "pagedjs" ]
6+
7+
[extra.typesetter_args]
8+
pagedjs = "--additional-script data/decasify.js"
69
+++
710

811
Coders have it easy.
@@ -12,6 +15,6 @@ Each language comes with its own challenges, and most have more than one style g
1215
In the case of English, even the style guides can leave much up to interpretation.
1316

1417
This demo is interesting not because different typesetting engines handle this either the same or differently, but because one library can be used in more than one engine.
15-
Specifically the [decasify](https://github.com/alerque/decasify) project implements various prose casing functions and can be used as a native package in either SILE or Typst, while Glu uses a small wrapper function around it's command line interface.
18+
Specifically the [decasify](https://github.com/alerque/decasify) project implements various prose casing functions and can be used as a native package in either SILE or Typst, Glu uses a small wrapper function around it's command line interface, and Paged JS uses a JavaScript wrapper that makes the WASM module available to the typesetter.
1619

17-
This demonstrates all included engines effectively passing the content to the same casing library, with the caveat that Glu does not track the language attribute on specific text spans and pass them to the shaper. SILE and Typst both demonstrate the surrounding document context being maintained both into and out of the filter and hence into the final text shaping.
20+
This demonstrates all included engines effectively passing the content to the same casing library, with the caveat that Glu does not track the language attribute on specific text spans and pass them to the shaper. SILE, Typst, and Paged JS demonstrate the surrounding document context being maintained both into and out of the filter and hence into the final text shaping.

‎data/title-case/pagedjs.html‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<html>
2+
<head>
3+
<style>
4+
@page {
5+
size: A6;
6+
bleed: 0;
7+
margin: 1cm;
8+
}
9+
h1 {
10+
font-size: 18pt;
11+
margin: 0;
12+
}
13+
p {
14+
margin: 0;
15+
}
16+
p + h1 {
17+
margin-top: 1em;
18+
}
19+
</style>
20+
</head>
21+
<body>
22+
<script>
23+
/* See caveat in src/build.js ... this inline script is some LLM generated
24+
* monkey business to trigger our sample generator after an async WASM module
25+
* is loaded and before Paged JS starts doing a layout pass.
26+
* I'd love to see a contribution from somebody that does thiskkome saner way.
27+
*/
28+
window.externalLibs = window.externalLibs || {};
29+
window.externalLibs.decasifyReady = new Promise(function (resolve) {
30+
window.externalLibs._resolveDecasifyReady = resolve;
31+
});
32+
</script>
33+
<script>
34+
window.generateSample = function (container) {
35+
var decasify = externalLibs.decasify;
36+
var Locale = decasify.Locale;
37+
var DefaultStyle = decasify.StyleGuide.LanguageDefault;
38+
39+
var examples = [
40+
{ text: "first impulse", lang: "en", loc: Locale.EN },
41+
{ text: "FIRST IMPULSE", lang: "en", loc: Locale.EN },
42+
{ text: "ilk ışıltı", lang: "tr", loc: Locale.TR },
43+
{ text: "İLK IŞILTI", lang: "tr", loc: Locale.TR },
44+
];
45+
46+
var cases = [
47+
{ name: "title", fn: function (text, locale) { return decasify.titlecase(text, locale, DefaultStyle); } },
48+
{ name: "lower", fn: decasify.lowercase },
49+
{ name: "upper", fn: decasify.uppercase },
50+
{ name: "sentence", fn: decasify.sentencecase },
51+
];
52+
53+
for (var ci = 0; ci < cases.length; ci++) {
54+
var entry = cases[ci];
55+
var heading = document.createElement("h1");
56+
heading.textContent = decasify.titlecase(entry.name + "case", Locale.EN, DefaultStyle);
57+
container.appendChild(heading);
58+
59+
for (var j = 0; j < examples.length; j++) {
60+
var example = examples[j];
61+
var p = document.createElement("p");
62+
p.textContent = "[" + example.lang + "] " + example.text + " → " + entry.fn(example.text, example.loc);
63+
container.appendChild(p);
64+
}
65+
}
66+
};
67+
</script>
68+
</body>
69+
</html>

‎package-lock.json‎

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"@codemirror/theme-one-dark": "^6.1.3",
1515
"@codemirror/view": "^6.43.9",
1616
"codemirror-lang-latex": "^0.6.1",
17-
"codemirror-lang-typst": "^0.6.0"
17+
"codemirror-lang-typst": "^0.6.0",
18+
"decasify": "^0.11.4"
1819
},
1920
"devDependencies": {
2021
"autoprefixer": "^10.5.4",
@@ -25,5 +26,8 @@
2526
"pagedjs-cli": "^0.4.3",
2627
"postcss-cli": "^11.0.1",
2728
"sass": "^1.103.1"
29+
},
30+
"allowScripts": {
31+
"decasify@0.11.4": true
2832
}
2933
}

‎src/decasify-bundle.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { titlecase, lowercase, uppercase, sentencecase, Locale, StyleGuide } from 'decasify';
2+
3+
externalLibs.decasify = { titlecase, lowercase, uppercase, sentencecase, Locale, StyleGuide };

0 commit comments

Comments
 (0)