@pretextbook/pretext-html 0.1.1 → 0.3.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.
Files changed (121) hide show
  1. package/README.md +82 -1
  2. package/assets/preview-html.xsl +0 -0
  3. package/assets/upstream.json +0 -0
  4. package/assets/xsl/README.md +0 -0
  5. package/assets/xsl/entities.ent +0 -0
  6. package/assets/xsl/extract-asymptote.xsl +0 -0
  7. package/assets/xsl/extract-biblio-csl.xsl +0 -0
  8. package/assets/xsl/extract-datafile.xsl +0 -0
  9. package/assets/xsl/extract-dynamic.xsl +0 -0
  10. package/assets/xsl/extract-identity.xsl +0 -0
  11. package/assets/xsl/extract-interactive.xsl +0 -0
  12. package/assets/xsl/extract-latex-image.xsl +0 -0
  13. package/assets/xsl/extract-mermaid.xsl +0 -0
  14. package/assets/xsl/extract-mom.xsl +0 -0
  15. package/assets/xsl/extract-pg.xsl +0 -0
  16. package/assets/xsl/extract-prefigure.xsl +0 -0
  17. package/assets/xsl/extract-qrcode.xsl +0 -0
  18. package/assets/xsl/extract-runestone-page-template.xsl +0 -0
  19. package/assets/xsl/extract-sageplot.xsl +0 -0
  20. package/assets/xsl/extract-stack.xsl +0 -0
  21. package/assets/xsl/extract-trace.xsl +0 -0
  22. package/assets/xsl/extract-youtube.xsl +0 -0
  23. package/assets/xsl/html-symbols.xsl +0 -0
  24. package/assets/xsl/latex/pretext-latex-AIM.xsl +0 -0
  25. package/assets/xsl/latex/pretext-latex-CLP.xsl +0 -0
  26. package/assets/xsl/latex/pretext-latex-chaos.xsl +0 -0
  27. package/assets/xsl/latex/pretext-latex-dyslexic-font.xsl +0 -0
  28. package/assets/xsl/latex/pretext-latex-guide.xsl +0 -0
  29. package/assets/xsl/latex/pretext-latex-texstyle.xsl +0 -0
  30. package/assets/xsl/localizations/README.md +0 -0
  31. package/assets/xsl/localizations/af-ZA.xml +0 -0
  32. package/assets/xsl/localizations/bg-BG.xml +0 -0
  33. package/assets/xsl/localizations/ca-ES.xml +0 -0
  34. package/assets/xsl/localizations/cs-CZ.xml +0 -0
  35. package/assets/xsl/localizations/de-DE.xml +0 -0
  36. package/assets/xsl/localizations/en-US.xml +0 -0
  37. package/assets/xsl/localizations/es-ES.xml +0 -0
  38. package/assets/xsl/localizations/fi-FI.xml +0 -0
  39. package/assets/xsl/localizations/fr-CA.xml +0 -0
  40. package/assets/xsl/localizations/fr-FR.xml +0 -0
  41. package/assets/xsl/localizations/hu-HU.xml +0 -0
  42. package/assets/xsl/localizations/it-IT.xml +0 -0
  43. package/assets/xsl/localizations/ku-CKB.xml +0 -0
  44. package/assets/xsl/localizations/localizations.xml +0 -0
  45. package/assets/xsl/localizations/nl-NL.xml +0 -0
  46. package/assets/xsl/localizations/pt-BR.xml +0 -0
  47. package/assets/xsl/localizations/pt-PT.xml +0 -0
  48. package/assets/xsl/localizations/zh-HANS.xml +0 -0
  49. package/assets/xsl/pretext-assembly.xsl +0 -0
  50. package/assets/xsl/pretext-basic-html.xsl +0 -0
  51. package/assets/xsl/pretext-beamer.xsl +0 -0
  52. package/assets/xsl/pretext-braille-preprint.xsl +0 -0
  53. package/assets/xsl/pretext-common.xsl +0 -0
  54. package/assets/xsl/pretext-dynamic.xsl +0 -0
  55. package/assets/xsl/pretext-epub.xsl +0 -0
  56. package/assets/xsl/pretext-fo.xsl +0 -0
  57. package/assets/xsl/pretext-html.xsl +0 -0
  58. package/assets/xsl/pretext-json-manifest.xsl +0 -0
  59. package/assets/xsl/pretext-jupyter.xsl +0 -0
  60. package/assets/xsl/pretext-latex-classic.xsl +0 -0
  61. package/assets/xsl/pretext-latex-common.xsl +0 -0
  62. package/assets/xsl/pretext-latex.xsl +0 -0
  63. package/assets/xsl/pretext-litprog.xsl +0 -0
  64. package/assets/xsl/pretext-merge.xsl +0 -0
  65. package/assets/xsl/pretext-numbers.xsl +0 -0
  66. package/assets/xsl/pretext-revealjs.xsl +0 -0
  67. package/assets/xsl/pretext-runestone-fitb.xsl +0 -0
  68. package/assets/xsl/pretext-runestone-static.xsl +0 -0
  69. package/assets/xsl/pretext-runestone.xsl +0 -0
  70. package/assets/xsl/pretext-sage-doctest.xsl +0 -0
  71. package/assets/xsl/pretext-smc.xsl +0 -0
  72. package/assets/xsl/pretext-solution-manual-latex.xsl +0 -0
  73. package/assets/xsl/pretext-text-utilities.xsl +0 -0
  74. package/assets/xsl/pretext-text.xsl +0 -0
  75. package/assets/xsl/pretext-units.xsl +0 -0
  76. package/assets/xsl/pretext-view-source.xsl +0 -0
  77. package/assets/xsl/pretext-ww-problem-sets.xsl +0 -0
  78. package/assets/xsl/publisher-variables.xsl +0 -0
  79. package/assets/xsl/support/README.md +0 -0
  80. package/assets/xsl/support/extract-math.xsl +0 -0
  81. package/assets/xsl/support/package-math.xsl +0 -0
  82. package/assets/xsl/support/play-button/README.md +0 -0
  83. package/assets/xsl/support/play-button/play-button.png +0 -0
  84. package/assets/xsl/support/play-button/play-button.svg +0 -0
  85. package/assets/xsl/support/pretext-pg-macros.xsl +0 -0
  86. package/assets/xsl/support/webpack_static_imports.xml +0 -0
  87. package/assets/xsl/tests/README.md +0 -0
  88. package/assets/xsl/tests/null.xml +0 -0
  89. package/assets/xsl/tests/pretext-text-utilities-test.xsl +0 -0
  90. package/assets/xsl/utilities/README.md +0 -0
  91. package/assets/xsl/utilities/author-report.xsl +0 -0
  92. package/assets/xsl/utilities/deprecate-autoname.sed +0 -0
  93. package/assets/xsl/utilities/deprecate-index.sed +0 -0
  94. package/assets/xsl/utilities/fix-deprecations.xsl +0 -0
  95. package/assets/xsl/utilities/pretext-enhanced-source.xsl +0 -0
  96. package/assets/xsl/utilities/report-publisher-variables.xsl +0 -0
  97. package/assets/xsl/xml-to-json.xsl +0 -0
  98. package/assets/xsl/xml-to-string.xsl +0 -0
  99. package/assets/xsl-bundle.json +1 -0
  100. package/dist/assets.d.ts +43 -0
  101. package/dist/assets.js +76 -0
  102. package/dist/cli-CzoinNle.js +639 -0
  103. package/dist/cli.d.ts +0 -0
  104. package/dist/cli.js +1 -1
  105. package/dist/host.browser.d.ts +29 -0
  106. package/dist/host.d.ts +41 -0
  107. package/dist/index.browser.d.ts +29 -0
  108. package/dist/index.browser.js +701 -0
  109. package/dist/index.d.ts +8 -0
  110. package/dist/index.js +20 -13
  111. package/dist/internal/posix-path.d.ts +59 -0
  112. package/dist/missing-asset.d.ts +31 -0
  113. package/dist/mounts.d.ts +18 -0
  114. package/dist/publication.d.ts +27 -0
  115. package/dist/renderer.d.ts +33 -1
  116. package/dist/sourcemap.d.ts +0 -0
  117. package/dist/theme.d.ts +0 -0
  118. package/dist/theme.js +0 -0
  119. package/dist/xinclude.d.ts +0 -0
  120. package/package.json +17 -3
  121. package/dist/cli-BQizBK0N.js +0 -555
@@ -0,0 +1,701 @@
1
+ import { fromXml as x } from "xast-util-from-xml";
2
+ import { toXml as $ } from "xast-util-to-xml";
3
+ const P = "/";
4
+ function me(e) {
5
+ if (!e)
6
+ return ".";
7
+ const t = e.startsWith("/"), n = e.length > 1 && e.endsWith("/"), r = [];
8
+ for (const i of e.split("/"))
9
+ if (!(!i || i === ".")) {
10
+ if (i === "..") {
11
+ const s = r[r.length - 1];
12
+ r.length > 0 && s !== ".." ? r.pop() : t || r.push("..");
13
+ continue;
14
+ }
15
+ r.push(i);
16
+ }
17
+ let o = r.join("/");
18
+ return t && (o = `/${o}`), o ? (n && !o.endsWith("/") && (o += "/"), o) : t ? "/" : ".";
19
+ }
20
+ function h(...e) {
21
+ let t = "";
22
+ for (let r = e.length - 1; r >= 0; r--) {
23
+ const o = e[r];
24
+ if (o && (t = t ? `${o}/${t}` : o, o.startsWith("/")))
25
+ break;
26
+ }
27
+ t.startsWith("/") || (t = `/${t}`);
28
+ const n = me(t);
29
+ return n.length > 1 && n.endsWith("/") ? n.slice(0, -1) : n;
30
+ }
31
+ function b(e) {
32
+ const t = e.replace(/\/+$/, "");
33
+ if (!t)
34
+ return e.startsWith("/") ? "/" : ".";
35
+ const n = t.lastIndexOf("/");
36
+ return n < 0 ? "." : n === 0 ? "/" : t.slice(0, n);
37
+ }
38
+ function S(e, t) {
39
+ const n = h(e).split("/").filter(Boolean), r = h(t).split("/").filter(Boolean);
40
+ let o = 0;
41
+ for (; o < n.length && o < r.length && n[o] === r[o]; )
42
+ o += 1;
43
+ return [...new Array(n.length - o).fill(".."), ...r.slice(o)].join("/");
44
+ }
45
+ const pe = "https://cdn.jsdelivr.net/npm/@pretextbook/pretext-html@0.3.0/assets";
46
+ let V;
47
+ function Ge(e) {
48
+ V = e.replace(/\/+$/, "");
49
+ }
50
+ function T() {
51
+ return V ?? pe;
52
+ }
53
+ function Q(e, t) {
54
+ return `${e.replace(/\/+$/, "")}/${t.replace(/^\/+/, "")}`;
55
+ }
56
+ const C = /* @__PURE__ */ new Map();
57
+ function we(e) {
58
+ return `${e.replace(/\/+$/, "")}-bundle.json`;
59
+ }
60
+ function ge(e) {
61
+ let t = C.get(e);
62
+ return t || (t = (async () => {
63
+ try {
64
+ const n = await fetch(we(e));
65
+ if (!n.ok)
66
+ return /* @__PURE__ */ new Map();
67
+ const r = await n.json();
68
+ return new Map(Object.entries(r));
69
+ } catch {
70
+ return /* @__PURE__ */ new Map();
71
+ }
72
+ })(), C.set(e, t)), t;
73
+ }
74
+ function ye(e) {
75
+ return e === Q(T(), "xsl");
76
+ }
77
+ async function Z(e, t) {
78
+ if (ye(e)) {
79
+ const i = (await ge(e)).get(t.replace(/^\/+/, ""));
80
+ if (i !== void 0)
81
+ return new TextEncoder().encode(i);
82
+ }
83
+ const n = `${e.replace(/\/+$/, "")}/`;
84
+ let r;
85
+ try {
86
+ r = new URL(t.replace(/^\/+/, ""), n);
87
+ } catch {
88
+ return;
89
+ }
90
+ if (!r.href.startsWith(n)) {
91
+ console.error(
92
+ `pretext-html: refusing to serve ${t} from outside ${e}`
93
+ );
94
+ return;
95
+ }
96
+ try {
97
+ const o = await fetch(r.href);
98
+ return o.ok ? new Uint8Array(await o.arrayBuffer()) : void 0;
99
+ } catch {
100
+ return;
101
+ }
102
+ }
103
+ async function L(e) {
104
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(e))
105
+ try {
106
+ const t = await fetch(e);
107
+ return t.ok ? await t.text() : void 0;
108
+ } catch {
109
+ return;
110
+ }
111
+ }
112
+ const F = /* @__PURE__ */ new Map(), ee = /* @__PURE__ */ new Map();
113
+ let _, be = 0, te = Z;
114
+ function Ke(e) {
115
+ te = e;
116
+ }
117
+ function ve(e, t) {
118
+ const n = typeof e == "string" ? e : e instanceof URL ? e.href : e.url, r = ee.get(n);
119
+ if (r !== void 0)
120
+ return Promise.resolve(new Response(r, { status: 200 }));
121
+ let o;
122
+ try {
123
+ o = new URL(n).host;
124
+ } catch {
125
+ o = "";
126
+ }
127
+ const i = F.get(o);
128
+ return i !== void 0 ? Ee(i, n) : _(e, t);
129
+ }
130
+ const xe = '<?xml version="1.0"?><pretext-preview-missing-file/>';
131
+ async function Ee(e, t) {
132
+ const n = decodeURIComponent(new URL(t).pathname), r = await te(e, n);
133
+ if (r === void 0)
134
+ return new Response(xe, { status: 200 });
135
+ const o = typeof r == "string" ? r : new Uint8Array(r);
136
+ return new Response(o, { status: 200 });
137
+ }
138
+ function ne() {
139
+ _ || (_ = globalThis.fetch, globalThis.fetch = ve);
140
+ }
141
+ function re(e) {
142
+ ne();
143
+ const t = `mnt${++be}.ptx.invalid`;
144
+ return F.set(t, e), `http://${t}`;
145
+ }
146
+ function $e(e) {
147
+ F.delete(new URL(e).host);
148
+ }
149
+ function Te(e, t) {
150
+ ne(), ee.set(e, t);
151
+ }
152
+ const oe = `<?xml version="1.0" encoding="UTF-8"?>
153
+ <publication>
154
+ <source>
155
+ <directories external="../assets" generated="../generated-assets" />
156
+ </source>
157
+ <html>
158
+ <platform portable="yes"/>
159
+ </html>
160
+ </publication>
161
+ `;
162
+ function y(e, t) {
163
+ for (const n of e.children)
164
+ if (n.type === "element" && n.name === t)
165
+ return n;
166
+ }
167
+ function U(e, t) {
168
+ let n = y(e, t);
169
+ return n || (n = { type: "element", name: t, attributes: {}, children: [] }, e.children.push(n)), n;
170
+ }
171
+ function H(e) {
172
+ if (!e)
173
+ return oe;
174
+ const t = x(e), n = y(t, "publication");
175
+ if (!n)
176
+ throw new Error(
177
+ "Invalid publication file: no root <publication> element found"
178
+ );
179
+ const r = U(n, "html"), o = U(r, "platform");
180
+ return o.attributes = { ...o.attributes, portable: "yes" }, $(t);
181
+ }
182
+ function O(e) {
183
+ if (!(e === void 0 || e === "" || e.startsWith("/")))
184
+ return e.endsWith("/") ? e : `${e}/`;
185
+ }
186
+ function ke(e) {
187
+ const t = x(e ?? oe), n = y(t, "publication"), r = n && y(n, "source"), o = r && y(r, "directories"), i = O(
188
+ o?.attributes?.external ?? void 0
189
+ ), s = O(
190
+ o?.attributes?.generated ?? void 0
191
+ );
192
+ return {
193
+ external: i,
194
+ generated: s,
195
+ managed: i !== void 0 && s !== void 0
196
+ };
197
+ }
198
+ const ie = "http://www.w3.org/2001/XInclude", N = 64;
199
+ async function Me(e, t, n) {
200
+ return e.includes("include") ? (await se(e, t, n)).content : e;
201
+ }
202
+ async function se(e, t, n) {
203
+ const r = x(e), o = {
204
+ projectDir: h(n),
205
+ stack: [h(t)]
206
+ }, i = await v(
207
+ r,
208
+ b(h(t)),
209
+ { "": "" },
210
+ o
211
+ );
212
+ return { tree: r, content: i ? $(r) : e };
213
+ }
214
+ function De(e) {
215
+ return e.data?.ptxIncludedFile;
216
+ }
217
+ function Se(e, t) {
218
+ const n = e.data ?? (e.data = {});
219
+ n.ptxIncludedFile = t;
220
+ }
221
+ function k(e, t) {
222
+ let n = e;
223
+ for (const [r, o] of Object.entries(t.attributes))
224
+ (r === "xmlns" || r.startsWith("xmlns:")) && (n === e && (n = { ...e }), n[r === "xmlns" ? "" : r.slice(6)] = o ?? "");
225
+ return n;
226
+ }
227
+ function ae(e, t) {
228
+ const n = e.name.indexOf(":"), r = n === -1 ? "" : e.name.slice(0, n);
229
+ return (n === -1 ? e.name : e.name.slice(n + 1)) === "include" && t[r] === ie;
230
+ }
231
+ async function v(e, t, n, r) {
232
+ let o = !1;
233
+ for (let i = 0; i < e.children.length; i++) {
234
+ const s = e.children[i];
235
+ if (s.type !== "element")
236
+ continue;
237
+ const a = k(n, s);
238
+ if (ae(s, a)) {
239
+ const d = await ce(
240
+ s,
241
+ t,
242
+ a,
243
+ r
244
+ );
245
+ e.children.splice(i, 1, ...d), i += d.length - 1, o = !0;
246
+ } else await v(s, t, a, r) && (o = !0);
247
+ }
248
+ return o;
249
+ }
250
+ async function ce(e, t, n, r) {
251
+ const o = r.stack[r.stack.length - 1];
252
+ if (e.attributes.xpointer)
253
+ throw new Error(
254
+ `xi:include with xpointer is not supported by the JS preview build (in ${o})`
255
+ );
256
+ const i = e.attributes.href;
257
+ if (!i)
258
+ throw new Error(`xi:include without href (in ${o})`);
259
+ let s = i;
260
+ try {
261
+ s = decodeURIComponent(i);
262
+ } catch {
263
+ }
264
+ const a = h(t, s);
265
+ if (a !== r.projectDir && !a.startsWith(r.projectDir + P))
266
+ throw new Error(
267
+ `xi:include escapes the project directory: ${i} (in ${o})`
268
+ );
269
+ if (r.stack.includes(a))
270
+ throw new Error(
271
+ `Circular xi:include: ${[...r.stack, a].join(" -> ")}`
272
+ );
273
+ if (r.stack.length >= N)
274
+ throw new Error(`xi:include nesting exceeds ${N} levels`);
275
+ const d = await L(a);
276
+ if (d === void 0) {
277
+ const f = Ae(e, n);
278
+ if (f)
279
+ return await v(f, t, n, r), f.children;
280
+ throw new Error(`xi:include target not found: ${i} (in ${o})`);
281
+ }
282
+ if (e.attributes.parse === "text")
283
+ return [{ type: "text", value: d }];
284
+ let c;
285
+ try {
286
+ c = x(d);
287
+ } catch (f) {
288
+ throw new Error(
289
+ `Could not parse xi:include target ${a} as XML: ${f instanceof Error ? f.message : f}. (Included files must be well-formed, with a single root element.)`
290
+ );
291
+ }
292
+ r.stack.push(a);
293
+ try {
294
+ await v(c, b(a), { "": "" }, r);
295
+ } finally {
296
+ r.stack.pop();
297
+ }
298
+ const u = c.children.filter(
299
+ (f) => f.type === "element"
300
+ );
301
+ for (const f of u)
302
+ Se(f, a);
303
+ return u;
304
+ }
305
+ function z(e) {
306
+ return e.name === "docinfo";
307
+ }
308
+ async function Ie(e, t, n) {
309
+ try {
310
+ const o = x(e).children.find(
311
+ (c) => c.type === "element"
312
+ );
313
+ if (!o)
314
+ return;
315
+ const i = h(t), s = b(i), a = {
316
+ projectDir: h(n),
317
+ stack: [i]
318
+ }, d = k({ "": "" }, o);
319
+ for (const c of o.children) {
320
+ if (c.type !== "element")
321
+ continue;
322
+ const u = k(d, c);
323
+ if (z(c))
324
+ return await v(c, s, u, a), $(c);
325
+ if (ae(c, u)) {
326
+ const m = (await ce(
327
+ c,
328
+ s,
329
+ u,
330
+ a
331
+ )).find(
332
+ (w) => w.type === "element" && z(w)
333
+ );
334
+ if (m)
335
+ return $(m);
336
+ continue;
337
+ }
338
+ break;
339
+ }
340
+ return;
341
+ } catch {
342
+ return;
343
+ }
344
+ }
345
+ function Ae(e, t) {
346
+ for (const n of e.children) {
347
+ if (n.type !== "element")
348
+ continue;
349
+ const r = k(t, n), o = n.name.indexOf(":"), i = o === -1 ? "" : n.name.slice(0, o);
350
+ if ((o === -1 ? n.name : n.name.slice(o + 1)) === "fallback" && r[i] === ie)
351
+ return n;
352
+ }
353
+ }
354
+ function le(e) {
355
+ return typeof e == "object" && e !== null && e.type === "element";
356
+ }
357
+ function Pe(e) {
358
+ return /^(pf|xhtml):/.test(e.name);
359
+ }
360
+ function _e(e, t, n) {
361
+ const r = [], o = e.children.find(le);
362
+ if (o) {
363
+ const i = n?.parentId ?? "root";
364
+ de(o, i, n?.position ?? 1, t, i, r);
365
+ }
366
+ return r;
367
+ }
368
+ function de(e, t, n, r, o, i) {
369
+ const s = De(e) ?? r;
370
+ let a, d;
371
+ if (Pe(e))
372
+ d = "root";
373
+ else {
374
+ const u = e.attributes.label ?? e.attributes["xml:id"];
375
+ a = u ?? `${t}-${n}`, i.push({
376
+ id: a,
377
+ file: s,
378
+ line: e.position?.start.line ?? 1,
379
+ column: e.position?.start.column ?? 1,
380
+ endLine: e.position?.end.line ?? e.position?.start.line ?? 1,
381
+ parent: o
382
+ }), d = a;
383
+ }
384
+ let c = 0;
385
+ for (const u of e.children)
386
+ le(u) && (c += 1, de(
387
+ u,
388
+ d,
389
+ c,
390
+ s,
391
+ a ?? o,
392
+ i
393
+ ));
394
+ }
395
+ function qe(e, t) {
396
+ let n;
397
+ for (const r of e)
398
+ r.line <= t && (n = r);
399
+ return n ?? e[0];
400
+ }
401
+ const ue = "pretext-html:set-theme";
402
+ function Ve(e) {
403
+ return e === "dark" || e === "light" || e === "system";
404
+ }
405
+ function Qe(e) {
406
+ return { type: ue, theme: e };
407
+ }
408
+ function Le(e) {
409
+ return [
410
+ "<script>",
411
+ "(function () {",
412
+ " var CFG = " + JSON.stringify({ msg: ue, initial: e }) + ";",
413
+ // Where the last requested theme is remembered so it survives an in-place
414
+ // document rewrite (same Window) and outranks the baked initial value.
415
+ " var KEY = '__ptxPreviewTheme';",
416
+ " var MEDIA = '(prefers-color-scheme: dark)';",
417
+ " function isTheme(v) {",
418
+ " return v === 'dark' || v === 'light' || v === 'system';",
419
+ " }",
420
+ " function prefersDark() {",
421
+ " return !!(window.matchMedia && window.matchMedia(MEDIA).matches);",
422
+ " }",
423
+ " function resolveDark(theme) {",
424
+ " if (theme === 'dark') return true;",
425
+ " if (theme === 'light') return false;",
426
+ " return prefersDark();",
427
+ // "system"
428
+ " }",
429
+ " function current() {",
430
+ " return isTheme(window[KEY]) ? window[KEY] : CFG.initial;",
431
+ " }",
432
+ // A theme with no dark variant marks the root data-darkmode="disabled";
433
+ // never force dark mode on in that case (mirrors setDarkMode's own guard).
434
+ " function darkModeDisabled() {",
435
+ " var el = document.documentElement;",
436
+ " return !!(el && el.dataset && el.dataset.darkmode === 'disabled');",
437
+ " }",
438
+ " function apply(theme) {",
439
+ " window[KEY] = theme;",
440
+ " if (darkModeDisabled()) return;",
441
+ " var dark = resolveDark(theme);",
442
+ // Toggle the class setDarkMode would set, right now, so an explicit theme
443
+ // does not flash before pretext-core.js defines setDarkMode. setDarkMode
444
+ // (once available) then does the complete job, including iframes.
445
+ " var el = document.documentElement;",
446
+ " if (el && el.classList) { el.classList.toggle('dark-mode', dark); }",
447
+ " if (typeof window.setDarkMode === 'function') { window.setDarkMode(dark); }",
448
+ " }",
449
+ " function reapply() { apply(current()); }",
450
+ // Immediately (no-op until setDarkMode exists), then again once the page's
451
+ // own script has defined it.
452
+ " reapply();",
453
+ " document.addEventListener('DOMContentLoaded', reapply);",
454
+ " window.addEventListener('load', reapply);",
455
+ // Embedder -> preview live updates.
456
+ " if (window.__ptxThemeMsgHandler) {",
457
+ " window.removeEventListener('message', window.__ptxThemeMsgHandler);",
458
+ " }",
459
+ " window.__ptxThemeMsgHandler = function (event) {",
460
+ " var data = event && event.data;",
461
+ " if (data && data.type === CFG.msg && isTheme(data.theme)) {",
462
+ " apply(data.theme);",
463
+ " }",
464
+ " };",
465
+ " window.addEventListener('message', window.__ptxThemeMsgHandler);",
466
+ // Track OS changes while following the system theme.
467
+ " if (window.matchMedia) {",
468
+ " var mq = window.matchMedia(MEDIA);",
469
+ " if (window.__ptxThemeMediaHandler) {",
470
+ " try { mq.removeEventListener('change', window.__ptxThemeMediaHandler); } catch (e) {}",
471
+ " }",
472
+ " window.__ptxThemeMediaHandler = function () {",
473
+ " if (current() === 'system') { reapply(); }",
474
+ " };",
475
+ " try { mq.addEventListener('change', window.__ptxThemeMediaHandler); } catch (e) {}",
476
+ " }",
477
+ "})();",
478
+ "<\/script>"
479
+ ].join(`
480
+ `);
481
+ }
482
+ function Fe(e, t) {
483
+ const n = Le(t);
484
+ return /<head[^>]*>/i.test(e) ? e.replace(/<head([^>]*)>/i, `<head$1>
485
+ ${n}`) : e;
486
+ }
487
+ function je() {
488
+ return Q(T(), "xsl");
489
+ }
490
+ function Re() {
491
+ return "Suspending" in WebAssembly;
492
+ }
493
+ function We() {
494
+ if (!Re())
495
+ throw new Error(
496
+ "WebAssembly JSPI is not enabled. Run Node with --experimental-wasm-jspi (or use the pretext-html CLI, which re-launches itself with the flag)."
497
+ );
498
+ }
499
+ function J(e) {
500
+ return e.includes("'") ? e.includes('"') ? `concat(${e.split("'").map((n) => `'${n}'`).join(`, "'", `)})` : `"${e}"` : `'${e}'`;
501
+ }
502
+ function Be(e) {
503
+ return e.replace(
504
+ /from '\.\/(https:\/\/[^']+)'/g,
505
+ (t, n) => `from '${n}'`
506
+ );
507
+ }
508
+ function Xe(e) {
509
+ return e.slice(0, 65536).replace(/<\?[\s\S]*?\?>/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<!DOCTYPE[^>]*>/gi, " ").match(/<\s*([A-Za-z][\w:-]*)/)?.[1];
510
+ }
511
+ async function Y(e) {
512
+ const t = await L(e);
513
+ if (t === void 0)
514
+ throw new Error(
515
+ `Could not read ${e}. (In the browser build only absolute URLs are readable — pass sourceContent instead of relying on sourcePath.)`
516
+ );
517
+ return t;
518
+ }
519
+ async function Ce(e, t) {
520
+ const n = h(e), r = await L(n);
521
+ if (r !== void 0)
522
+ return Ie(r, n, t);
523
+ }
524
+ function Ue(e, t, n) {
525
+ const r = e.replace(/^\uFEFF/, "").replace(/<\?xml[\s\S]*?\?>/, "").replace(/<!DOCTYPE[^>]*>/i, ""), o = t === "chapter" || t === "part" ? "book" : "article";
526
+ return `<pretext>
527
+ ${n?.trim() ? `${n.trim()}
528
+ ` : ""}<${o}>
529
+ <title/>
530
+ ${r}
531
+ </${o}>
532
+ </pretext>
533
+ `;
534
+ }
535
+ let fe = !1;
536
+ function He(e) {
537
+ return e instanceof Error && /\bAborted\(/.test(e.message);
538
+ }
539
+ function Oe(e) {
540
+ return e instanceof Error && /memory access|out of bounds/i.test(e.message);
541
+ }
542
+ function Ne() {
543
+ if (fe)
544
+ throw new Error(
545
+ "The WebAssembly renderer aborted earlier in this process and cannot be reused. Restart the process (or reload the page) to render again."
546
+ );
547
+ }
548
+ function G(e) {
549
+ if (He(e))
550
+ throw fe = !0, new Error(
551
+ "The WebAssembly renderer aborted and cannot be reused. Restart the process (or reload the page) to render again.",
552
+ { cause: e }
553
+ );
554
+ if (Oe(e))
555
+ throw new Error(
556
+ "The WebAssembly renderer hit a memory fault. Most often the document is too large for this build's stack — whole-book builds are a known limitation, so try a smaller document, or see the README about rebuilding libxslt-wasm with a larger stack. The same fault also results from running two renders concurrently against the shared libxslt state.",
557
+ { cause: e }
558
+ );
559
+ }
560
+ let I;
561
+ async function he() {
562
+ return I || (I = (async () => {
563
+ const [e, t] = await Promise.all([
564
+ import("@pretextbook/libxslt-wasm"),
565
+ import("@pretextbook/libxslt-wasm/exslt")
566
+ ]);
567
+ return t.registerAll(), e;
568
+ })()), I;
569
+ }
570
+ const A = /* @__PURE__ */ new Map();
571
+ async function ze(e) {
572
+ const t = e;
573
+ let n = A.get(t);
574
+ return n || (n = (async () => {
575
+ const { XmlDocument: r, XsltStylesheet: o } = await he(), i = re(t), s = await Z(
576
+ T(),
577
+ "/preview-html.xsl"
578
+ );
579
+ if (s === void 0)
580
+ throw new Error(
581
+ `Could not read preview-html.xsl from ${T()}. Check the assets location (PRETEXT_HTML_ASSETS under Node, setAssetsBase() in the browser).`
582
+ );
583
+ const a = new TextDecoder().decode(s), d = await r.fromString(a, {
584
+ url: `${i}/preview-html.xsl`,
585
+ options: { noEnt: !0, dtdLoad: !0, huge: !0 }
586
+ });
587
+ return o.fromXmlDocument(d);
588
+ })(), A.set(t, n), n.catch(() => A.delete(t))), n;
589
+ }
590
+ let K = Promise.resolve();
591
+ function Ze(e) {
592
+ const t = K.then(
593
+ () => q(e),
594
+ () => q(e)
595
+ );
596
+ return K = t.catch(() => {
597
+ }), t;
598
+ }
599
+ async function q(e) {
600
+ We(), Ne();
601
+ const { XmlDocument: t } = await he(), n = await ze(e.xslDir ?? je()), r = h(e.sourcePath), o = h(
602
+ e.projectDir ?? b(r)
603
+ ), i = e.sourceContent ?? await Y(r), s = S(o, r);
604
+ if (s.startsWith(".."))
605
+ throw new Error(
606
+ `sourcePath (${r}) must live inside projectDir (${o})`
607
+ );
608
+ const a = S(
609
+ o,
610
+ h(e.mainSourcePath ?? r)
611
+ ), d = a.startsWith("..") ? s : a, c = re(o);
612
+ try {
613
+ let u, f = `${c}/__pretext-preview-publication.xml`;
614
+ if (e.publicationPath) {
615
+ const l = h(e.publicationPath);
616
+ u = H(
617
+ await Y(l)
618
+ );
619
+ const g = S(o, l);
620
+ g.startsWith("..") || (f = `${c}/${g.split(P).join("/")}`);
621
+ } else
622
+ u = H();
623
+ Te(f, u);
624
+ const m = ke(u), w = b(h(o, d)), j = m.external !== void 0 && m.generated !== void 0 ? {
625
+ external: h(w, m.external),
626
+ generated: h(w, m.generated)
627
+ } : void 0;
628
+ let M, p;
629
+ if (e.sourceMap) {
630
+ const l = await se(
631
+ i,
632
+ r,
633
+ o
634
+ );
635
+ M = l.tree, p = l.content;
636
+ } else
637
+ p = await Me(
638
+ i,
639
+ r,
640
+ o
641
+ );
642
+ const E = Xe(p);
643
+ let R = { parentId: "root", position: 1 };
644
+ if (E !== "pretext" && E !== "mathbook")
645
+ if (e.fragment) {
646
+ const l = e.docinfo ?? (e.docinfoSourcePath ? await Ce(e.docinfoSourcePath, o) : void 0);
647
+ p = Ue(p, E, l), R = { parentId: l?.trim() ? "root-1-2" : "root-1-1", position: 2 };
648
+ } else
649
+ throw new Error(
650
+ `The document root is <${E ?? "?"}>, not <pretext> — this looks like an xi:included fragment. Render the project's main source file instead, or pass the fragment option.`
651
+ );
652
+ const W = M ? _e(M, r, R) : void 0, B = await t.fromString(p, {
653
+ url: `${c}/${d.split(P).join("/")}`,
654
+ options: { noEnt: !0, dtdLoad: !0, huge: !0 }
655
+ }), X = {
656
+ publisher: J(f)
657
+ };
658
+ for (const [l, g] of Object.entries(e.stringParams ?? {}))
659
+ X[l] = J(g);
660
+ let D;
661
+ try {
662
+ D = await n.apply(B, X);
663
+ } catch (l) {
664
+ throw G(l), new Error(
665
+ "PreTeXt XSLT transform failed; see the PTX:ERROR/PTX:FATAL messages on stderr for details.",
666
+ { cause: l }
667
+ );
668
+ } finally {
669
+ B.delete();
670
+ }
671
+ try {
672
+ let l = Be(D.toHtmlString());
673
+ return e.theme && (l = Fe(l, e.theme)), {
674
+ html: l,
675
+ ...W ? { sourceMap: W } : {},
676
+ ...j ? { assetDirs: j } : {}
677
+ };
678
+ } catch (l) {
679
+ throw G(l), l;
680
+ } finally {
681
+ D.delete();
682
+ }
683
+ } finally {
684
+ $e(c);
685
+ }
686
+ }
687
+ export {
688
+ ue as PREVIEW_THEME_MESSAGE,
689
+ je as defaultXslDir,
690
+ qe as findSourceMapEntry,
691
+ H as forcePortablePublication,
692
+ Fe as injectThemeBridge,
693
+ Re as isJspiAvailable,
694
+ Ve as isPreviewTheme,
695
+ Qe as previewThemeMessage,
696
+ Ze as renderHtml,
697
+ Ge as setAssetsBase,
698
+ Ke as setMountReader,
699
+ Le as themeBridgeScript,
700
+ J as xpathStringLiteral
701
+ };
package/dist/index.d.ts CHANGED
@@ -3,6 +3,14 @@ export type { RenderOptions, RenderResult } from './renderer.js';
3
3
  export { findSourceMapEntry } from './sourcemap.js';
4
4
  export type { PtxSourceMap, SourceMapEntry } from './sourcemap.js';
5
5
  export { forcePortablePublication } from './publication.js';
6
+ export { rewriteAssetUrls } from './assets.js';
7
+ export type { AssetKind, AssetUrlResolver } from './assets.js';
8
+ export { describeAsset, missingAssetPlaceholder, missingAssetSvg, } from './missing-asset.js';
9
+ export type { MissingAsset } from './missing-asset.js';
10
+ export type { AssetDirectories } from './publication.js';
6
11
  export { PREVIEW_THEME_MESSAGE, isPreviewTheme, previewThemeMessage, themeBridgeScript, injectThemeBridge, } from './theme.js';
7
12
  export type { PreviewTheme, PreviewThemeMessage } from './theme.js';
8
13
  export { main as runCli } from './cli.js';
14
+ export { setAssetsBase } from './host.js';
15
+ export { setMountReader } from './mounts.js';
16
+ export type { MountReader } from './mounts.js';