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