@pretextbook/pretext-html 0.1.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 +160 -0
- package/assets/preview-html.xsl +230 -0
- package/assets/upstream.json +7 -0
- package/assets/xsl/README.md +31 -0
- package/assets/xsl/entities.ent +154 -0
- package/assets/xsl/extract-asymptote.xsl +68 -0
- package/assets/xsl/extract-biblio-csl.xsl +327 -0
- package/assets/xsl/extract-datafile.xsl +71 -0
- package/assets/xsl/extract-dynamic.xsl +139 -0
- package/assets/xsl/extract-identity.xsl +136 -0
- package/assets/xsl/extract-interactive.xsl +81 -0
- package/assets/xsl/extract-latex-image.xsl +118 -0
- package/assets/xsl/extract-mermaid.xsl +58 -0
- package/assets/xsl/extract-mom.xsl +63 -0
- package/assets/xsl/extract-pg.xsl +2897 -0
- package/assets/xsl/extract-prefigure.xsl +157 -0
- package/assets/xsl/extract-qrcode.xsl +100 -0
- package/assets/xsl/extract-runestone-page-template.xsl +139 -0
- package/assets/xsl/extract-sageplot.xsl +166 -0
- package/assets/xsl/extract-stack.xsl +56 -0
- package/assets/xsl/extract-trace.xsl +134 -0
- package/assets/xsl/extract-youtube.xsl +63 -0
- package/assets/xsl/html-symbols.xsl +3344 -0
- package/assets/xsl/latex/pretext-latex-AIM.xsl +56 -0
- package/assets/xsl/latex/pretext-latex-CLP.xsl +148 -0
- package/assets/xsl/latex/pretext-latex-chaos.xsl +317 -0
- package/assets/xsl/latex/pretext-latex-dyslexic-font.xsl +76 -0
- package/assets/xsl/latex/pretext-latex-guide.xsl +104 -0
- package/assets/xsl/latex/pretext-latex-texstyle.xsl +862 -0
- package/assets/xsl/localizations/README.md +56 -0
- package/assets/xsl/localizations/af-ZA.xml +276 -0
- package/assets/xsl/localizations/bg-BG.xml +276 -0
- package/assets/xsl/localizations/ca-ES.xml +285 -0
- package/assets/xsl/localizations/cs-CZ.xml +280 -0
- package/assets/xsl/localizations/de-DE.xml +281 -0
- package/assets/xsl/localizations/en-US.xml +427 -0
- package/assets/xsl/localizations/es-ES.xml +287 -0
- package/assets/xsl/localizations/fi-FI.xml +275 -0
- package/assets/xsl/localizations/fr-CA.xml +276 -0
- package/assets/xsl/localizations/fr-FR.xml +280 -0
- package/assets/xsl/localizations/hu-HU.xml +280 -0
- package/assets/xsl/localizations/it-IT.xml +276 -0
- package/assets/xsl/localizations/ku-CKB.xml +275 -0
- package/assets/xsl/localizations/localizations.xml +48 -0
- package/assets/xsl/localizations/nl-NL.xml +275 -0
- package/assets/xsl/localizations/pt-BR.xml +288 -0
- package/assets/xsl/localizations/pt-PT.xml +292 -0
- package/assets/xsl/localizations/zh-HANS.xml +269 -0
- package/assets/xsl/pretext-assembly.xsl +4795 -0
- package/assets/xsl/pretext-basic-html.xsl +86 -0
- package/assets/xsl/pretext-beamer.xsl +662 -0
- package/assets/xsl/pretext-braille-preprint.xsl +2249 -0
- package/assets/xsl/pretext-common.xsl +12018 -0
- package/assets/xsl/pretext-dynamic.xsl +65 -0
- package/assets/xsl/pretext-epub.xsl +1483 -0
- package/assets/xsl/pretext-fo.xsl +4593 -0
- package/assets/xsl/pretext-html.xsl +14791 -0
- package/assets/xsl/pretext-json-manifest.xsl +150 -0
- package/assets/xsl/pretext-jupyter.xsl +868 -0
- package/assets/xsl/pretext-latex-classic.xsl +952 -0
- package/assets/xsl/pretext-latex-common.xsl +11563 -0
- package/assets/xsl/pretext-latex.xsl +47 -0
- package/assets/xsl/pretext-litprog.xsl +105 -0
- package/assets/xsl/pretext-merge.xsl +41 -0
- package/assets/xsl/pretext-numbers.xsl +875 -0
- package/assets/xsl/pretext-revealjs.xsl +522 -0
- package/assets/xsl/pretext-runestone-fitb.xsl +1233 -0
- package/assets/xsl/pretext-runestone-static.xsl +1438 -0
- package/assets/xsl/pretext-runestone.xsl +3083 -0
- package/assets/xsl/pretext-sage-doctest.xsl +289 -0
- package/assets/xsl/pretext-smc.xsl +492 -0
- package/assets/xsl/pretext-solution-manual-latex.xsl +323 -0
- package/assets/xsl/pretext-text-utilities.xsl +1217 -0
- package/assets/xsl/pretext-text.xsl +392 -0
- package/assets/xsl/pretext-units.xsl +195 -0
- package/assets/xsl/pretext-view-source.xsl +157 -0
- package/assets/xsl/pretext-ww-problem-sets.xsl +391 -0
- package/assets/xsl/publisher-variables.xsl +4756 -0
- package/assets/xsl/support/README.md +22 -0
- package/assets/xsl/support/extract-math.xsl +256 -0
- package/assets/xsl/support/package-math.xsl +141 -0
- package/assets/xsl/support/play-button/README.md +46 -0
- package/assets/xsl/support/play-button/play-button.png +0 -0
- package/assets/xsl/support/play-button/play-button.svg +3 -0
- package/assets/xsl/support/pretext-pg-macros.xsl +110 -0
- package/assets/xsl/support/webpack_static_imports.xml +14 -0
- package/assets/xsl/tests/README.md +24 -0
- package/assets/xsl/tests/null.xml +4 -0
- package/assets/xsl/tests/pretext-text-utilities-test.xsl +334 -0
- package/assets/xsl/utilities/README.md +31 -0
- package/assets/xsl/utilities/author-report.xsl +107 -0
- package/assets/xsl/utilities/deprecate-autoname.sed +18 -0
- package/assets/xsl/utilities/deprecate-index.sed +33 -0
- package/assets/xsl/utilities/fix-deprecations.xsl +663 -0
- package/assets/xsl/utilities/pretext-enhanced-source.xsl +112 -0
- package/assets/xsl/utilities/report-publisher-variables.xsl +162 -0
- package/assets/xsl/xml-to-json.xsl +326 -0
- package/assets/xsl/xml-to-string.xsl +328 -0
- package/cli.mjs +29 -0
- package/dist/cli-C6tfAVvi.js +553 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +7 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +10 -0
- package/dist/mounts.d.ts +23 -0
- package/dist/publication.d.ts +16 -0
- package/dist/renderer.d.ts +84 -0
- package/dist/sourcemap.d.ts +41 -0
- package/dist/xinclude.d.ts +45 -0
- package/package.json +52 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
import { readFile as m, writeFile as j } from "node:fs/promises";
|
|
2
|
+
import * as w from "node:process";
|
|
3
|
+
import * as c from "node:path";
|
|
4
|
+
import { fileURLToPath as K } from "node:url";
|
|
5
|
+
import { fromXml as $ } from "xast-util-from-xml";
|
|
6
|
+
import { toXml as y } from "xast-util-to-xml";
|
|
7
|
+
const I = /* @__PURE__ */ new Map(), W = /* @__PURE__ */ new Map();
|
|
8
|
+
let S, Q = 0;
|
|
9
|
+
function ee(e, r) {
|
|
10
|
+
const t = typeof e == "string" ? e : e instanceof URL ? e.href : e.url, n = W.get(t);
|
|
11
|
+
if (n !== void 0)
|
|
12
|
+
return Promise.resolve(new Response(n, { status: 200 }));
|
|
13
|
+
let o;
|
|
14
|
+
try {
|
|
15
|
+
o = new URL(t).host;
|
|
16
|
+
} catch {
|
|
17
|
+
o = "";
|
|
18
|
+
}
|
|
19
|
+
const i = I.get(o);
|
|
20
|
+
return i !== void 0 ? te(i, t) : S(e, r);
|
|
21
|
+
}
|
|
22
|
+
const F = '<?xml version="1.0"?><pretext-preview-missing-file/>';
|
|
23
|
+
async function te(e, r) {
|
|
24
|
+
const t = decodeURIComponent(new URL(r).pathname), n = c.resolve(e, "." + c.posix.normalize(t));
|
|
25
|
+
if (n !== e && !n.startsWith(e + c.sep))
|
|
26
|
+
return console.error(
|
|
27
|
+
`pretext-html: refusing to serve ${t} from outside ${e}`
|
|
28
|
+
), new Response(F, { status: 200 });
|
|
29
|
+
try {
|
|
30
|
+
const o = await m(n);
|
|
31
|
+
return new Response(new Uint8Array(o), { status: 200 });
|
|
32
|
+
} catch {
|
|
33
|
+
return new Response(F, { status: 200 });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function N() {
|
|
37
|
+
S || (S = globalThis.fetch, globalThis.fetch = ee);
|
|
38
|
+
}
|
|
39
|
+
function B(e) {
|
|
40
|
+
N();
|
|
41
|
+
const r = `mnt${++Q}.ptx.invalid`;
|
|
42
|
+
return I.set(r, c.resolve(e)), `http://${r}`;
|
|
43
|
+
}
|
|
44
|
+
function re(e) {
|
|
45
|
+
I.delete(new URL(e).host);
|
|
46
|
+
}
|
|
47
|
+
function ne(e, r) {
|
|
48
|
+
N(), W.set(e, r);
|
|
49
|
+
}
|
|
50
|
+
const oe = `<?xml version="1.0" encoding="UTF-8"?>
|
|
51
|
+
<publication>
|
|
52
|
+
<source>
|
|
53
|
+
<directories external="../assets" generated="../generated-assets" />
|
|
54
|
+
</source>
|
|
55
|
+
<html>
|
|
56
|
+
<platform portable="yes"/>
|
|
57
|
+
</html>
|
|
58
|
+
</publication>
|
|
59
|
+
`;
|
|
60
|
+
function _(e, r) {
|
|
61
|
+
for (const t of e.children)
|
|
62
|
+
if (t.type === "element" && t.name === r)
|
|
63
|
+
return t;
|
|
64
|
+
}
|
|
65
|
+
function M(e, r) {
|
|
66
|
+
let t = _(e, r);
|
|
67
|
+
return t || (t = { type: "element", name: r, attributes: {}, children: [] }, e.children.push(t)), t;
|
|
68
|
+
}
|
|
69
|
+
function L(e) {
|
|
70
|
+
if (!e)
|
|
71
|
+
return oe;
|
|
72
|
+
const r = $(e), t = _(r, "publication");
|
|
73
|
+
if (!t)
|
|
74
|
+
throw new Error(
|
|
75
|
+
"Invalid publication file: no root <publication> element found"
|
|
76
|
+
);
|
|
77
|
+
const n = M(t, "html"), o = M(n, "platform");
|
|
78
|
+
return o.attributes = { ...o.attributes, portable: "yes" }, y(r);
|
|
79
|
+
}
|
|
80
|
+
const H = "http://www.w3.org/2001/XInclude", R = 64;
|
|
81
|
+
async function ie(e, r, t) {
|
|
82
|
+
return e.includes("include") ? (await J(e, r, t)).content : e;
|
|
83
|
+
}
|
|
84
|
+
async function J(e, r, t) {
|
|
85
|
+
const n = $(e), o = {
|
|
86
|
+
projectDir: c.resolve(t),
|
|
87
|
+
stack: [c.resolve(r)]
|
|
88
|
+
}, i = await x(
|
|
89
|
+
n,
|
|
90
|
+
c.dirname(c.resolve(r)),
|
|
91
|
+
{ "": "" },
|
|
92
|
+
o
|
|
93
|
+
);
|
|
94
|
+
return { tree: n, content: i ? y(n) : e };
|
|
95
|
+
}
|
|
96
|
+
function se(e) {
|
|
97
|
+
return e.data?.ptxIncludedFile;
|
|
98
|
+
}
|
|
99
|
+
function ae(e, r) {
|
|
100
|
+
const t = e.data ?? (e.data = {});
|
|
101
|
+
t.ptxIncludedFile = r;
|
|
102
|
+
}
|
|
103
|
+
function v(e, r) {
|
|
104
|
+
let t = e;
|
|
105
|
+
for (const [n, o] of Object.entries(r.attributes))
|
|
106
|
+
(n === "xmlns" || n.startsWith("xmlns:")) && (t === e && (t = { ...e }), t[n === "xmlns" ? "" : n.slice(6)] = o ?? "");
|
|
107
|
+
return t;
|
|
108
|
+
}
|
|
109
|
+
function q(e, r) {
|
|
110
|
+
const t = e.name.indexOf(":"), n = t === -1 ? "" : e.name.slice(0, t);
|
|
111
|
+
return (t === -1 ? e.name : e.name.slice(t + 1)) === "include" && r[n] === H;
|
|
112
|
+
}
|
|
113
|
+
async function x(e, r, t, n) {
|
|
114
|
+
let o = !1;
|
|
115
|
+
for (let i = 0; i < e.children.length; i++) {
|
|
116
|
+
const l = e.children[i];
|
|
117
|
+
if (l.type !== "element")
|
|
118
|
+
continue;
|
|
119
|
+
const s = v(t, l);
|
|
120
|
+
if (q(l, s)) {
|
|
121
|
+
const f = await z(
|
|
122
|
+
l,
|
|
123
|
+
r,
|
|
124
|
+
s,
|
|
125
|
+
n
|
|
126
|
+
);
|
|
127
|
+
e.children.splice(i, 1, ...f), i += f.length - 1, o = !0;
|
|
128
|
+
} else await x(l, r, s, n) && (o = !0);
|
|
129
|
+
}
|
|
130
|
+
return o;
|
|
131
|
+
}
|
|
132
|
+
async function z(e, r, t, n) {
|
|
133
|
+
const o = n.stack[n.stack.length - 1];
|
|
134
|
+
if (e.attributes.xpointer)
|
|
135
|
+
throw new Error(
|
|
136
|
+
`xi:include with xpointer is not supported by the JS preview build (in ${o})`
|
|
137
|
+
);
|
|
138
|
+
const i = e.attributes.href;
|
|
139
|
+
if (!i)
|
|
140
|
+
throw new Error(`xi:include without href (in ${o})`);
|
|
141
|
+
let l = i;
|
|
142
|
+
try {
|
|
143
|
+
l = decodeURIComponent(i);
|
|
144
|
+
} catch {
|
|
145
|
+
}
|
|
146
|
+
const s = c.resolve(r, l);
|
|
147
|
+
if (s !== n.projectDir && !s.startsWith(n.projectDir + c.sep))
|
|
148
|
+
throw new Error(
|
|
149
|
+
`xi:include escapes the project directory: ${i} (in ${o})`
|
|
150
|
+
);
|
|
151
|
+
if (n.stack.includes(s))
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Circular xi:include: ${[...n.stack, s].join(" -> ")}`
|
|
154
|
+
);
|
|
155
|
+
if (n.stack.length >= R)
|
|
156
|
+
throw new Error(`xi:include nesting exceeds ${R} levels`);
|
|
157
|
+
let f;
|
|
158
|
+
try {
|
|
159
|
+
f = await m(s, "utf8");
|
|
160
|
+
} catch {
|
|
161
|
+
const u = le(e, t);
|
|
162
|
+
if (u)
|
|
163
|
+
return await x(u, r, t, n), u.children;
|
|
164
|
+
throw new Error(`xi:include target not found: ${i} (in ${o})`);
|
|
165
|
+
}
|
|
166
|
+
if (e.attributes.parse === "text")
|
|
167
|
+
return [{ type: "text", value: f }];
|
|
168
|
+
let a;
|
|
169
|
+
try {
|
|
170
|
+
a = $(f);
|
|
171
|
+
} catch (u) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
`Could not parse xi:include target ${s} as XML: ${u instanceof Error ? u.message : u}. (Included files must be well-formed, with a single root element.)`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
n.stack.push(s);
|
|
177
|
+
try {
|
|
178
|
+
await x(a, c.dirname(s), { "": "" }, n);
|
|
179
|
+
} finally {
|
|
180
|
+
n.stack.pop();
|
|
181
|
+
}
|
|
182
|
+
const d = a.children.filter(
|
|
183
|
+
(u) => u.type === "element"
|
|
184
|
+
);
|
|
185
|
+
for (const u of d)
|
|
186
|
+
ae(u, s);
|
|
187
|
+
return d;
|
|
188
|
+
}
|
|
189
|
+
function A(e) {
|
|
190
|
+
return e.name === "docinfo";
|
|
191
|
+
}
|
|
192
|
+
async function ce(e, r, t) {
|
|
193
|
+
try {
|
|
194
|
+
const o = $(e).children.find(
|
|
195
|
+
(a) => a.type === "element"
|
|
196
|
+
);
|
|
197
|
+
if (!o)
|
|
198
|
+
return;
|
|
199
|
+
const i = c.resolve(r), l = c.dirname(i), s = {
|
|
200
|
+
projectDir: c.resolve(t),
|
|
201
|
+
stack: [i]
|
|
202
|
+
}, f = v({ "": "" }, o);
|
|
203
|
+
for (const a of o.children) {
|
|
204
|
+
if (a.type !== "element")
|
|
205
|
+
continue;
|
|
206
|
+
const d = v(f, a);
|
|
207
|
+
if (A(a))
|
|
208
|
+
return await x(a, l, d, s), y(a);
|
|
209
|
+
if (q(a, d)) {
|
|
210
|
+
const h = (await z(
|
|
211
|
+
a,
|
|
212
|
+
l,
|
|
213
|
+
d,
|
|
214
|
+
s
|
|
215
|
+
)).find(
|
|
216
|
+
(g) => g.type === "element" && A(g)
|
|
217
|
+
);
|
|
218
|
+
if (h)
|
|
219
|
+
return y(h);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
return;
|
|
225
|
+
} catch {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function le(e, r) {
|
|
230
|
+
for (const t of e.children) {
|
|
231
|
+
if (t.type !== "element")
|
|
232
|
+
continue;
|
|
233
|
+
const n = v(r, t), o = t.name.indexOf(":"), i = o === -1 ? "" : t.name.slice(0, o);
|
|
234
|
+
if ((o === -1 ? t.name : t.name.slice(o + 1)) === "fallback" && n[i] === H)
|
|
235
|
+
return t;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function G(e) {
|
|
239
|
+
return typeof e == "object" && e !== null && e.type === "element";
|
|
240
|
+
}
|
|
241
|
+
function ue(e) {
|
|
242
|
+
return /^(pf|xhtml):/.test(e.name);
|
|
243
|
+
}
|
|
244
|
+
function fe(e, r, t) {
|
|
245
|
+
const n = [], o = e.children.find(G);
|
|
246
|
+
if (o) {
|
|
247
|
+
const i = t?.parentId ?? "root";
|
|
248
|
+
Y(o, i, t?.position ?? 1, r, i, n);
|
|
249
|
+
}
|
|
250
|
+
return n;
|
|
251
|
+
}
|
|
252
|
+
function Y(e, r, t, n, o, i) {
|
|
253
|
+
const l = se(e) ?? n;
|
|
254
|
+
let s, f;
|
|
255
|
+
if (ue(e))
|
|
256
|
+
f = "root";
|
|
257
|
+
else {
|
|
258
|
+
const d = e.attributes.label ?? e.attributes["xml:id"];
|
|
259
|
+
s = d ?? `${r}-${t}`, i.push({
|
|
260
|
+
id: s,
|
|
261
|
+
file: l,
|
|
262
|
+
line: e.position?.start.line ?? 1,
|
|
263
|
+
column: e.position?.start.column ?? 1,
|
|
264
|
+
endLine: e.position?.end.line ?? e.position?.start.line ?? 1,
|
|
265
|
+
parent: o
|
|
266
|
+
}), f = s;
|
|
267
|
+
}
|
|
268
|
+
let a = 0;
|
|
269
|
+
for (const d of e.children)
|
|
270
|
+
G(d) && (a += 1, Y(
|
|
271
|
+
d,
|
|
272
|
+
f,
|
|
273
|
+
a,
|
|
274
|
+
l,
|
|
275
|
+
s ?? o,
|
|
276
|
+
i
|
|
277
|
+
));
|
|
278
|
+
}
|
|
279
|
+
function Ie(e, r) {
|
|
280
|
+
let t;
|
|
281
|
+
for (const n of e)
|
|
282
|
+
n.line <= r && (t = n);
|
|
283
|
+
return t ?? e[0];
|
|
284
|
+
}
|
|
285
|
+
function V() {
|
|
286
|
+
return process.env.PRETEXT_HTML_ASSETS ?? c.resolve(c.dirname(K(import.meta.url)), "..", "assets");
|
|
287
|
+
}
|
|
288
|
+
function de() {
|
|
289
|
+
return c.join(V(), "xsl");
|
|
290
|
+
}
|
|
291
|
+
function pe() {
|
|
292
|
+
return c.join(V(), "preview-html.xsl");
|
|
293
|
+
}
|
|
294
|
+
function he() {
|
|
295
|
+
return "Suspending" in WebAssembly;
|
|
296
|
+
}
|
|
297
|
+
function me() {
|
|
298
|
+
if (!he())
|
|
299
|
+
throw new Error(
|
|
300
|
+
"WebAssembly JSPI is not enabled. Run Node with --experimental-wasm-jspi (or use the pretext-html CLI, which re-launches itself with the flag)."
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
function U(e) {
|
|
304
|
+
return e.includes("'") ? e.includes('"') ? `concat(${e.split("'").map((t) => `'${t}'`).join(`, "'", `)})` : `"${e}"` : `'${e}'`;
|
|
305
|
+
}
|
|
306
|
+
function we(e) {
|
|
307
|
+
return e.replace(
|
|
308
|
+
/from '\.\/(https:\/\/[^']+)'/g,
|
|
309
|
+
(r, t) => `from '${t}'`
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
function ge(e) {
|
|
313
|
+
return e.slice(0, 65536).replace(/<\?[\s\S]*?\?>/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<!DOCTYPE[^>]*>/gi, " ").match(/<\s*([A-Za-z][\w:-]*)/)?.[1];
|
|
314
|
+
}
|
|
315
|
+
async function be(e, r) {
|
|
316
|
+
const t = c.resolve(e);
|
|
317
|
+
let n;
|
|
318
|
+
try {
|
|
319
|
+
n = await m(t, "utf8");
|
|
320
|
+
} catch {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
return ce(n, t, r);
|
|
324
|
+
}
|
|
325
|
+
function xe(e, r, t) {
|
|
326
|
+
const n = e.replace(/^\uFEFF/, "").replace(/<\?xml[\s\S]*?\?>/, "").replace(/<!DOCTYPE[^>]*>/i, ""), o = r === "chapter" || r === "part" ? "book" : "article";
|
|
327
|
+
return `<pretext>
|
|
328
|
+
${t?.trim() ? `${t.trim()}
|
|
329
|
+
` : ""}<${o}>
|
|
330
|
+
<title/>
|
|
331
|
+
${n}
|
|
332
|
+
</${o}>
|
|
333
|
+
</pretext>
|
|
334
|
+
`;
|
|
335
|
+
}
|
|
336
|
+
function C(e) {
|
|
337
|
+
if (e instanceof Error && /memory access|out of bounds/i.test(e.message))
|
|
338
|
+
throw new Error(
|
|
339
|
+
"The document is too large for the current WebAssembly build (stack overflow). Whole-book builds are a known limitation; try a smaller document, or see the README about rebuilding libxslt-wasm with a larger stack.",
|
|
340
|
+
{ cause: e }
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
let P;
|
|
344
|
+
async function Z() {
|
|
345
|
+
return P || (P = (async () => {
|
|
346
|
+
const [e, r] = await Promise.all([
|
|
347
|
+
import("@pretextbook/libxslt-wasm"),
|
|
348
|
+
import("@pretextbook/libxslt-wasm/exslt")
|
|
349
|
+
]);
|
|
350
|
+
return r.registerAll(), e;
|
|
351
|
+
})()), P;
|
|
352
|
+
}
|
|
353
|
+
const k = /* @__PURE__ */ new Map();
|
|
354
|
+
async function ye(e) {
|
|
355
|
+
const r = c.resolve(e);
|
|
356
|
+
let t = k.get(r);
|
|
357
|
+
return t || (t = (async () => {
|
|
358
|
+
const { XmlDocument: n, XsltStylesheet: o } = await Z(), i = B(r), l = await m(pe(), "utf8"), s = await n.fromString(l, {
|
|
359
|
+
url: `${i}/preview-html.xsl`,
|
|
360
|
+
options: { noEnt: !0, dtdLoad: !0, huge: !0 }
|
|
361
|
+
});
|
|
362
|
+
return o.fromXmlDocument(s);
|
|
363
|
+
})(), k.set(r, t), t.catch(() => k.delete(r))), t;
|
|
364
|
+
}
|
|
365
|
+
async function ve(e) {
|
|
366
|
+
me();
|
|
367
|
+
const { XmlDocument: r } = await Z(), t = await ye(e.xslDir ?? de()), n = c.resolve(e.sourcePath), o = c.resolve(
|
|
368
|
+
e.projectDir ?? c.dirname(n)
|
|
369
|
+
), i = e.sourceContent ?? await m(n, "utf8"), l = c.relative(o, n);
|
|
370
|
+
if (l.startsWith(".."))
|
|
371
|
+
throw new Error(
|
|
372
|
+
`sourcePath (${n}) must live inside projectDir (${o})`
|
|
373
|
+
);
|
|
374
|
+
const s = B(o);
|
|
375
|
+
try {
|
|
376
|
+
let f, a = `${s}/__pretext-preview-publication.xml`;
|
|
377
|
+
if (e.publicationPath) {
|
|
378
|
+
const p = c.resolve(e.publicationPath);
|
|
379
|
+
f = L(
|
|
380
|
+
await m(p, "utf8")
|
|
381
|
+
);
|
|
382
|
+
const b = c.relative(o, p);
|
|
383
|
+
b.startsWith("..") || (a = `${s}/${b.split(c.sep).join("/")}`);
|
|
384
|
+
} else
|
|
385
|
+
f = L();
|
|
386
|
+
ne(a, f);
|
|
387
|
+
let d, u;
|
|
388
|
+
if (e.sourceMap) {
|
|
389
|
+
const p = await J(
|
|
390
|
+
i,
|
|
391
|
+
n,
|
|
392
|
+
o
|
|
393
|
+
);
|
|
394
|
+
d = p.tree, u = p.content;
|
|
395
|
+
} else
|
|
396
|
+
u = await ie(
|
|
397
|
+
i,
|
|
398
|
+
n,
|
|
399
|
+
o
|
|
400
|
+
);
|
|
401
|
+
const h = ge(u);
|
|
402
|
+
let g = { parentId: "root", position: 1 };
|
|
403
|
+
if (h !== "pretext" && h !== "mathbook")
|
|
404
|
+
if (e.fragment) {
|
|
405
|
+
const p = e.docinfo ?? (e.docinfoSourcePath ? await be(e.docinfoSourcePath, o) : void 0);
|
|
406
|
+
u = xe(u, h, p), g = { parentId: p?.trim() ? "root-1-2" : "root-1-1", position: 2 };
|
|
407
|
+
} else
|
|
408
|
+
throw new Error(
|
|
409
|
+
`The document root is <${h ?? "?"}>, not <pretext> — this looks like an xi:included fragment. Render the project's main source file instead, or pass the fragment option.`
|
|
410
|
+
);
|
|
411
|
+
const T = d ? fe(d, n, g) : void 0, D = await r.fromString(u, {
|
|
412
|
+
url: `${s}/${l.split(c.sep).join("/")}`,
|
|
413
|
+
options: { noEnt: !0, dtdLoad: !0, huge: !0 }
|
|
414
|
+
}), X = {
|
|
415
|
+
publisher: U(a)
|
|
416
|
+
};
|
|
417
|
+
for (const [p, b] of Object.entries(e.stringParams ?? {}))
|
|
418
|
+
X[p] = U(b);
|
|
419
|
+
let E;
|
|
420
|
+
try {
|
|
421
|
+
E = await t.apply(D, X);
|
|
422
|
+
} catch (p) {
|
|
423
|
+
throw C(p), new Error(
|
|
424
|
+
"PreTeXt XSLT transform failed; see the PTX:ERROR/PTX:FATAL messages on stderr for details.",
|
|
425
|
+
{ cause: p }
|
|
426
|
+
);
|
|
427
|
+
} finally {
|
|
428
|
+
D.delete();
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
return {
|
|
432
|
+
html: we(E.toHtmlString()),
|
|
433
|
+
...T ? { sourceMap: T } : {}
|
|
434
|
+
};
|
|
435
|
+
} catch (p) {
|
|
436
|
+
throw C(p), p;
|
|
437
|
+
} finally {
|
|
438
|
+
E.delete();
|
|
439
|
+
}
|
|
440
|
+
} finally {
|
|
441
|
+
re(s);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
const O = `Usage: pretext-html <source.ptx> [options]
|
|
445
|
+
|
|
446
|
+
Render a PreTeXt document to a single standalone HTML page (portable build:
|
|
447
|
+
one page, css/js/MathJax from CDN). No PreTeXt installation required.
|
|
448
|
+
|
|
449
|
+
Options:
|
|
450
|
+
-o, --output <file> Write HTML to a file instead of stdout
|
|
451
|
+
--publication <file> Publication file (portable html is forced on)
|
|
452
|
+
--project-dir <dir> Directory served to the transform for xi:includes
|
|
453
|
+
(default: the source file's directory)
|
|
454
|
+
--param <name=value> Extra XSLT string parameter (repeatable)
|
|
455
|
+
--xsl-dir <dir> Use PreTeXt stylesheets from this directory
|
|
456
|
+
instead of the vendored copy
|
|
457
|
+
--fragment Allow a non-root source file: wrap the fragment
|
|
458
|
+
in a minimal <pretext> document (an <article>,
|
|
459
|
+
or a <book> for <chapter>/<part> fragments)
|
|
460
|
+
--docinfo <file> File whose contents (a <docinfo> element) are
|
|
461
|
+
injected into the wrapper in --fragment mode, so
|
|
462
|
+
the fragment keeps the project's LaTeX macros
|
|
463
|
+
--docinfo-source <file> Complete source file (e.g. main.ptx) to lift the
|
|
464
|
+
<docinfo> from for --fragment mode, resolving
|
|
465
|
+
xi:includes (used when --docinfo is not given)
|
|
466
|
+
--source-map <file> Also write a JSON source map: HTML id → source
|
|
467
|
+
file/line for every element (for editor sync)
|
|
468
|
+
-h, --help Show this help
|
|
469
|
+
`;
|
|
470
|
+
function $e(e) {
|
|
471
|
+
let r, t, n, o;
|
|
472
|
+
const i = {}, l = {};
|
|
473
|
+
for (let s = 0; s < e.length; s++) {
|
|
474
|
+
const f = e[s], a = () => {
|
|
475
|
+
if (s += 1, s >= e.length)
|
|
476
|
+
throw new Error(`Missing value for ${f}`);
|
|
477
|
+
return e[s];
|
|
478
|
+
};
|
|
479
|
+
switch (f) {
|
|
480
|
+
case "-h":
|
|
481
|
+
case "--help":
|
|
482
|
+
w.stdout.write(O), w.exit(0);
|
|
483
|
+
break;
|
|
484
|
+
case "-o":
|
|
485
|
+
case "--output":
|
|
486
|
+
t = a();
|
|
487
|
+
break;
|
|
488
|
+
case "--publication":
|
|
489
|
+
i.publicationPath = a();
|
|
490
|
+
break;
|
|
491
|
+
case "--project-dir":
|
|
492
|
+
i.projectDir = a();
|
|
493
|
+
break;
|
|
494
|
+
case "--xsl-dir":
|
|
495
|
+
i.xslDir = a();
|
|
496
|
+
break;
|
|
497
|
+
case "--fragment":
|
|
498
|
+
i.fragment = !0;
|
|
499
|
+
break;
|
|
500
|
+
case "--docinfo":
|
|
501
|
+
n = a();
|
|
502
|
+
break;
|
|
503
|
+
case "--docinfo-source":
|
|
504
|
+
i.docinfoSourcePath = a();
|
|
505
|
+
break;
|
|
506
|
+
case "--source-map":
|
|
507
|
+
o = a(), i.sourceMap = !0;
|
|
508
|
+
break;
|
|
509
|
+
case "--param": {
|
|
510
|
+
const d = a(), u = d.indexOf("=");
|
|
511
|
+
if (u === -1)
|
|
512
|
+
throw new Error(`--param expects name=value, got: ${d}`);
|
|
513
|
+
l[d.slice(0, u)] = d.slice(u + 1);
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
default:
|
|
517
|
+
if (f.startsWith("-"))
|
|
518
|
+
throw new Error(`Unknown option: ${f}`);
|
|
519
|
+
if (r)
|
|
520
|
+
throw new Error(`Unexpected extra argument: ${f}`);
|
|
521
|
+
r = f;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (!r)
|
|
525
|
+
throw new Error(`No source file given.
|
|
526
|
+
|
|
527
|
+
` + O);
|
|
528
|
+
return Object.keys(l).length > 0 && (i.stringParams = l), {
|
|
529
|
+
options: { ...i, sourcePath: r },
|
|
530
|
+
output: t,
|
|
531
|
+
docinfoPath: n,
|
|
532
|
+
sourceMapPath: o
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
async function Te(e) {
|
|
536
|
+
const { options: r, output: t, docinfoPath: n, sourceMapPath: o } = $e(e);
|
|
537
|
+
n && (r.docinfo = await m(n, "utf8"));
|
|
538
|
+
const i = Date.now(), { html: l, sourceMap: s } = await ve(r);
|
|
539
|
+
w.stderr.write(`pretext-html: rendered in ${Date.now() - i}ms
|
|
540
|
+
`), o && s && (await j(o, JSON.stringify(s, null, 2)), w.stderr.write(`pretext-html: wrote ${o}
|
|
541
|
+
`)), t ? (await j(t, l), w.stderr.write(`pretext-html: wrote ${t}
|
|
542
|
+
`)) : w.stdout.write(l);
|
|
543
|
+
}
|
|
544
|
+
export {
|
|
545
|
+
L as a,
|
|
546
|
+
de as d,
|
|
547
|
+
Ie as f,
|
|
548
|
+
he as i,
|
|
549
|
+
Te as m,
|
|
550
|
+
$e as p,
|
|
551
|
+
ve as r,
|
|
552
|
+
U as x
|
|
553
|
+
};
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RenderOptions } from './renderer.js';
|
|
2
|
+
interface CliArgs {
|
|
3
|
+
options: RenderOptions;
|
|
4
|
+
output?: string;
|
|
5
|
+
docinfoPath?: string;
|
|
6
|
+
sourceMapPath?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseArgs(argv: string[]): CliArgs;
|
|
9
|
+
export declare function main(argv: string[]): Promise<void>;
|
|
10
|
+
export {};
|
package/dist/cli.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { renderHtml, defaultXslDir, isJspiAvailable, xpathStringLiteral, } from './renderer.js';
|
|
2
|
+
export type { RenderOptions, RenderResult } from './renderer.js';
|
|
3
|
+
export { findSourceMapEntry } from './sourcemap.js';
|
|
4
|
+
export type { PtxSourceMap, SourceMapEntry } from './sourcemap.js';
|
|
5
|
+
export { forcePortablePublication } from './publication.js';
|
|
6
|
+
export { main as runCli } from './cli.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { d as i, f as s, a as e, i as l, r as t, m as n, x as o } from "./cli-C6tfAVvi.js";
|
|
2
|
+
export {
|
|
3
|
+
i as defaultXslDir,
|
|
4
|
+
s as findSourceMapEntry,
|
|
5
|
+
e as forcePortablePublication,
|
|
6
|
+
l as isJspiAvailable,
|
|
7
|
+
t as renderHtml,
|
|
8
|
+
n as runCli,
|
|
9
|
+
o as xpathStringLiteral
|
|
10
|
+
};
|
package/dist/mounts.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Virtual-host fetch shim.
|
|
3
|
+
*
|
|
4
|
+
* The libxslt-wasm build is compiled with FILESYSTEM=0, so libxml2 cannot
|
|
5
|
+
* touch the real filesystem: any `file://` URL aborts inside the WASM sandbox.
|
|
6
|
+
* Instead, every external resource load (stylesheet imports, DTD entities,
|
|
7
|
+
* xi:includes, the publication file, `document()` calls) is routed through the
|
|
8
|
+
* *global* `fetch` via a JSPI-suspended import. That makes resource loading
|
|
9
|
+
* fully controllable from JavaScript: we register fake hosts under the
|
|
10
|
+
* reserved `.invalid` TLD and serve them from local directories or in-memory
|
|
11
|
+
* strings. No HTTP server, no real network traffic.
|
|
12
|
+
*/
|
|
13
|
+
/** Install the shim (idempotent). Must run before libxslt-wasm loads anything. */
|
|
14
|
+
export declare function installFetchShim(): void;
|
|
15
|
+
/**
|
|
16
|
+
* Serve `dir` under a unique fake origin. Returns the base URL
|
|
17
|
+
* (e.g. `http://mnt1.ptx.invalid`); resource paths append to it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function mountDirectory(dir: string): string;
|
|
20
|
+
export declare function unmountDirectory(baseUrl: string): void;
|
|
21
|
+
/** Serve `content` for exactly `url`. Takes priority over directory mounts. */
|
|
22
|
+
export declare function setVirtualFile(url: string, content: string): void;
|
|
23
|
+
export declare function removeVirtualFile(url: string): void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Publication-file handling for single-page preview builds.
|
|
3
|
+
*
|
|
4
|
+
* The preview relies on PreTeXt's "portable HTML" mode
|
|
5
|
+
* (`<html><platform portable="yes"/></html>` in the publication file), which
|
|
6
|
+
* forces chunk level 0 (the whole document on one page), serves css/js from
|
|
7
|
+
* the jsDelivr CDN, and suppresses most auxiliary file output. Publisher
|
|
8
|
+
* variables can only come from a publication file — there is no stringparam
|
|
9
|
+
* for `portable` — so we rewrite the user's publication file (or synthesize a
|
|
10
|
+
* minimal one) and serve it through the fetch shim as a virtual file.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Return publication-file XML with `<html><platform portable="yes"/></html>`
|
|
14
|
+
* forced, preserving everything else from `publicationXml` when given.
|
|
15
|
+
*/
|
|
16
|
+
export declare function forcePortablePublication(publicationXml?: string): string;
|