@pretextbook/pretext-html 0.5.0 → 0.7.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 (99) hide show
  1. package/README.md +6 -0
  2. package/assets/preview-html.xsl +14 -0
  3. package/assets/upstream.json +1 -1
  4. package/assets/xsl/LICENSE-pretext +1 -1
  5. package/assets/xsl/README.md +43 -25
  6. package/assets/xsl/entities.ent +4 -4
  7. package/assets/xsl/extract-asymptote.xsl +5 -5
  8. package/assets/xsl/extract-biblio-csl.xsl +1 -1
  9. package/assets/xsl/extract-datafile.xsl +1 -1
  10. package/assets/xsl/extract-dynamic.xsl +1 -1
  11. package/assets/xsl/extract-identity.xsl +5 -5
  12. package/assets/xsl/extract-interactive.xsl +1 -1
  13. package/assets/xsl/extract-latex-image.xsl +5 -5
  14. package/assets/xsl/extract-mermaid.xsl +1 -1
  15. package/assets/xsl/extract-mom.xsl +5 -5
  16. package/assets/xsl/extract-pg.xsl +1 -1
  17. package/assets/xsl/extract-prefigure.xsl +5 -5
  18. package/assets/xsl/extract-qrcode.xsl +1 -1
  19. package/assets/xsl/extract-runestone-page-template.xsl +1 -1
  20. package/assets/xsl/extract-sageplot.xsl +5 -5
  21. package/assets/xsl/extract-stack.xsl +1 -1
  22. package/assets/xsl/extract-trace.xsl +1 -1
  23. package/assets/xsl/extract-youtube.xsl +5 -5
  24. package/assets/xsl/latex/pretext-latex-AIM.xsl +1 -1
  25. package/assets/xsl/latex/pretext-latex-chaos.xsl +1 -1
  26. package/assets/xsl/latex/pretext-latex-dyslexic-font.xsl +1 -1
  27. package/assets/xsl/latex/pretext-latex-guide.xsl +1 -1
  28. package/assets/xsl/localizations/README.md +25 -25
  29. package/assets/xsl/localizations/af-ZA.xml +1 -1
  30. package/assets/xsl/localizations/bg-BG.xml +1 -1
  31. package/assets/xsl/localizations/ca-ES.xml +1 -1
  32. package/assets/xsl/localizations/cs-CZ.xml +1 -1
  33. package/assets/xsl/localizations/de-DE.xml +1 -1
  34. package/assets/xsl/localizations/en-US.xml +1 -1
  35. package/assets/xsl/localizations/es-ES.xml +1 -1
  36. package/assets/xsl/localizations/fi-FI.xml +1 -1
  37. package/assets/xsl/localizations/fr-CA.xml +1 -1
  38. package/assets/xsl/localizations/fr-FR.xml +1 -1
  39. package/assets/xsl/localizations/hu-HU.xml +1 -1
  40. package/assets/xsl/localizations/it-IT.xml +1 -1
  41. package/assets/xsl/localizations/ku-CKB.xml +1 -1
  42. package/assets/xsl/localizations/localizations.xml +1 -1
  43. package/assets/xsl/localizations/nl-NL.xml +1 -1
  44. package/assets/xsl/localizations/pt-BR.xml +1 -1
  45. package/assets/xsl/localizations/pt-PT.xml +1 -1
  46. package/assets/xsl/localizations/zh-HANS.xml +1 -1
  47. package/assets/xsl/pretext-assembly.xsl +64 -1
  48. package/assets/xsl/pretext-basic-html.xsl +5 -5
  49. package/assets/xsl/pretext-braille-preprint.xsl +5 -5
  50. package/assets/xsl/pretext-common.xsl +104 -30
  51. package/assets/xsl/pretext-dynamic.xsl +1 -1
  52. package/assets/xsl/pretext-epub.xsl +90 -84
  53. package/assets/xsl/pretext-fo.xsl +1 -1
  54. package/assets/xsl/pretext-html.xsl +57 -34
  55. package/assets/xsl/pretext-json-manifest.xsl +1 -1
  56. package/assets/xsl/pretext-jupyter.xsl +5 -5
  57. package/assets/xsl/pretext-latex-classic.xsl +1 -1
  58. package/assets/xsl/pretext-latex-common.xsl +7 -5
  59. package/assets/xsl/pretext-latex.xsl +3 -3
  60. package/assets/xsl/pretext-litprog.xsl +9 -2
  61. package/assets/xsl/pretext-markdown.xsl +1 -1
  62. package/assets/xsl/pretext-numbers.xsl +1 -1
  63. package/assets/xsl/pretext-runestone-fitb.xsl +18 -0
  64. package/assets/xsl/pretext-runestone-static.xsl +13 -1
  65. package/assets/xsl/pretext-runestone.xsl +34 -6
  66. package/assets/xsl/pretext-sage-doctest.xsl +18 -0
  67. package/assets/xsl/pretext-solution-manual-latex.xsl +4 -4
  68. package/assets/xsl/pretext-text-utilities.xsl +1 -1
  69. package/assets/xsl/pretext-text.xsl +5 -5
  70. package/assets/xsl/pretext-units.xsl +5 -5
  71. package/assets/xsl/pretext-view-source.xsl +1 -1
  72. package/assets/xsl/pretext-ww-problem-sets.xsl +15 -12
  73. package/assets/xsl/publisher-variables.xsl +104 -36
  74. package/assets/xsl/support/README.md +19 -0
  75. package/assets/xsl/support/extract-math.xsl +1 -1
  76. package/assets/xsl/support/package-math.xsl +1 -1
  77. package/assets/xsl/support/play-button/README.md +3 -1
  78. package/assets/xsl/support/webpack_static_imports.xml +19 -0
  79. package/assets/xsl/tests/README.md +20 -1
  80. package/assets/xsl/tests/null.xml +19 -0
  81. package/assets/xsl/tests/pretext-text-utilities-test.xsl +1 -1
  82. package/assets/xsl/utilities/README.md +27 -6
  83. package/assets/xsl/utilities/author-report.xsl +1 -1
  84. package/assets/xsl/utilities/fix-deprecations.xsl +5 -5
  85. package/assets/xsl/utilities/pretext-enhanced-source.xsl +1 -1
  86. package/assets/xsl/utilities/report-publisher-variables.xsl +5 -5
  87. package/assets/xsl/xml-to-json.xsl +4 -4
  88. package/assets/xsl-bundle.json +1 -1
  89. package/dist/banner.d.ts +51 -0
  90. package/dist/{cli-DZsyZERX.js → cli-D0m0Ha1j.js} +358 -196
  91. package/dist/cli.js +2 -2
  92. package/dist/index.browser.d.ts +3 -0
  93. package/dist/index.browser.js +477 -322
  94. package/dist/index.d.ts +3 -0
  95. package/dist/index.js +25 -21
  96. package/dist/knowls.d.ts +43 -0
  97. package/dist/renderer.d.ts +26 -0
  98. package/package.json +1 -1
  99. package/assets/xsl/pretext-smc.xsl +0 -492
@@ -1,12 +1,141 @@
1
- import { readFile as A, writeFile as O } from "node:fs/promises";
1
+ import { readFile as A, writeFile as U } from "node:fs/promises";
2
2
  import * as b from "node:process";
3
3
  import * as l from "node:path";
4
4
  import { fileURLToPath as he } from "node:url";
5
- import { fromXml as x } from "xast-util-from-xml";
5
+ import { fromXml as y } from "xast-util-from-xml";
6
6
  import { toXml as $ } from "xast-util-to-xml";
7
- import { injectRevealBridge as me } from "./reveal.js";
8
- import { injectThemeBridge as pe } from "./theme.js";
9
- async function Q(e, r) {
7
+ import { injectRevealBridge as we } from "./reveal.js";
8
+ import { injectThemeBridge as be } from "./theme.js";
9
+ const ge = "ptxPreviewBannerDismissed", ve = "About live preview";
10
+ function N(e) {
11
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
12
+ }
13
+ function xe(e) {
14
+ return [
15
+ '<div id="ptx-preview-banner" class="ptx-preview-banner" role="note">',
16
+ ` <span class="ptx-preview-banner-text">${N(e)}</span>`,
17
+ ' <button type="button" class="ptx-preview-banner-dismiss" aria-label="Dismiss">&times;</button>',
18
+ "</div>",
19
+ `<button type="button" id="ptx-preview-banner-restore" class="ptx-preview-banner-restore" hidden>${N(ve)}</button>`
20
+ ].join(`
21
+ `);
22
+ }
23
+ function ye() {
24
+ return [
25
+ "<style>",
26
+ ".ptx-preview-banner {",
27
+ " display: flex;",
28
+ " align-items: center;",
29
+ " gap: 0.75em;",
30
+ " padding: 0.5em 1em;",
31
+ " font-size: 0.9em;",
32
+ " background: #fff8e1;",
33
+ " color: #6b5300;",
34
+ " border-bottom: 1px solid #f0c36d;",
35
+ "}",
36
+ // The [hidden] content attribute only hides an element via the
37
+ // user-agent stylesheet's `[hidden] { display: none }` rule, and a
38
+ // normal-priority *author* rule always wins over a normal-priority UA
39
+ // rule regardless of selector specificity — so the unconditional
40
+ // `display: flex` above would otherwise keep the banner visible even
41
+ // after previewBannerScript sets `banner.hidden = true`.
42
+ ".ptx-preview-banner[hidden] {",
43
+ " display: none;",
44
+ "}",
45
+ ".ptx-preview-banner-text {",
46
+ " flex: 1 1 auto;",
47
+ "}",
48
+ ".ptx-preview-banner-dismiss {",
49
+ " flex: 0 0 auto;",
50
+ " background: transparent;",
51
+ " border: none;",
52
+ " font-size: 1.2em;",
53
+ " line-height: 1;",
54
+ " cursor: pointer;",
55
+ " color: inherit;",
56
+ " padding: 0 0.25em;",
57
+ "}",
58
+ "html.dark-mode .ptx-preview-banner {",
59
+ " background: #3a2f00;",
60
+ " color: #f2d27a;",
61
+ " border-bottom-color: #6b5300;",
62
+ "}",
63
+ ".ptx-preview-banner-restore {",
64
+ " position: fixed;",
65
+ " right: 0.5em;",
66
+ " bottom: 0.5em;",
67
+ " z-index: 1000;",
68
+ " background: transparent;",
69
+ " border: none;",
70
+ " padding: 0.15em 0.4em;",
71
+ " font-size: 0.75em;",
72
+ " color: inherit;",
73
+ " opacity: 0.45;",
74
+ " text-decoration: underline;",
75
+ " cursor: pointer;",
76
+ "}",
77
+ ".ptx-preview-banner-restore:hover {",
78
+ " opacity: 0.85;",
79
+ "}",
80
+ "</style>"
81
+ ].join(`
82
+ `);
83
+ }
84
+ function Ee() {
85
+ return [
86
+ "<script>",
87
+ "(function () {",
88
+ " var KEY = " + JSON.stringify(ge) + ";",
89
+ ' var banner = document.getElementById("ptx-preview-banner");',
90
+ ' var restore = document.getElementById("ptx-preview-banner-restore");',
91
+ " if (!banner || !restore) { return; }",
92
+ // localStorage can throw (disabled cookies/storage, sandboxed iframe);
93
+ // fall back to always showing the banner rather than crashing the page.
94
+ " function isDismissed() {",
95
+ " try { return window.localStorage.getItem(KEY) === '1'; }",
96
+ " catch (e) { return false; }",
97
+ " }",
98
+ " function setDismissed(value) {",
99
+ " try {",
100
+ " if (value) { window.localStorage.setItem(KEY, '1'); }",
101
+ " else { window.localStorage.removeItem(KEY); }",
102
+ " } catch (e) {}",
103
+ " }",
104
+ " function apply(dismissed) {",
105
+ " banner.hidden = dismissed;",
106
+ " restore.hidden = !dismissed;",
107
+ " }",
108
+ " apply(isDismissed());",
109
+ ' var dismissBtn = banner.querySelector(".ptx-preview-banner-dismiss");',
110
+ " if (dismissBtn) {",
111
+ " dismissBtn.addEventListener('click', function () {",
112
+ " setDismissed(true);",
113
+ " apply(true);",
114
+ " });",
115
+ " }",
116
+ " restore.addEventListener('click', function () {",
117
+ " setDismissed(false);",
118
+ " apply(false);",
119
+ " });",
120
+ "})();",
121
+ "<\/script>"
122
+ ].join(`
123
+ `);
124
+ }
125
+ const Te = "<!--ptx-preview-banner-->", $e = "<!--/ptx-preview-banner-->", Se = /\n?<!--ptx-preview-banner-->[\s\S]*?<!--\/ptx-preview-banner-->/;
126
+ function ke(e, r) {
127
+ const t = Se.exec(e), n = t ? e.slice(0, t.index) + e.slice(t.index + t[0].length) : e;
128
+ if (!/<body[^>]*>/i.test(n))
129
+ return n;
130
+ const o = `
131
+ ${Te}
132
+ ${ye()}
133
+ ${xe(r.message)}
134
+ ${Ee()}
135
+ ${$e}`;
136
+ return n.replace(/<body([^>]*)>/i, `<body$1>${o}`);
137
+ }
138
+ async function ee(e, r) {
10
139
  const t = l.resolve(e), n = l.resolve(t, `.${l.posix.normalize(r)}`);
11
140
  if (n !== t && !n.startsWith(t + l.sep)) {
12
141
  console.error(
@@ -27,23 +156,45 @@ async function j(e) {
27
156
  return;
28
157
  }
29
158
  }
30
- let K;
31
- function st(e) {
32
- K = e;
159
+ let te;
160
+ function yt(e) {
161
+ te = e;
33
162
  }
34
163
  function I() {
35
- return K ?? process.env.PRETEXT_HTML_ASSETS ?? l.resolve(l.dirname(he(import.meta.url)), "..", "assets");
164
+ return te ?? process.env.PRETEXT_HTML_ASSETS ?? l.resolve(l.dirname(he(import.meta.url)), "..", "assets");
36
165
  }
37
- function we(e, r) {
166
+ function Pe(e, r) {
38
167
  return l.join(e, r);
39
168
  }
40
- const X = /* @__PURE__ */ new Map(), ee = /* @__PURE__ */ new Map();
41
- let M, be = 0, te = Q;
42
- function it(e) {
43
- te = e;
169
+ const De = "born-hidden-knowl", Ie = /<details\b([^>]*)>(\s*)(?:<summary\b([^>]*)>)?/g;
170
+ function Le(e) {
171
+ const r = /\bclass="([^"]*)"/.exec(e);
172
+ return r ? r[1].trim().split(/\s+/) : [];
173
+ }
174
+ function Re(e) {
175
+ return /(^|\s)open(\s|=|$)/.test(e);
176
+ }
177
+ function H(e) {
178
+ return Re(e) ? e : ` open${e}`;
44
179
  }
45
- function ge(e, r) {
46
- const t = typeof e == "string" ? e : e instanceof URL ? e.href : e.url, n = ee.get(t);
180
+ function Ae(e) {
181
+ return e.replace(
182
+ Ie,
183
+ (r, t, n, o) => {
184
+ if (!Le(t).includes(De))
185
+ return r;
186
+ const s = `<details${H(t)}>`;
187
+ return o === void 0 ? `${s}${n}` : `${s}${n}<summary${H(o)}>`;
188
+ }
189
+ );
190
+ }
191
+ const B = /* @__PURE__ */ new Map(), re = /* @__PURE__ */ new Map();
192
+ let L, je = 0, ne = ee;
193
+ function Et(e) {
194
+ ne = e;
195
+ }
196
+ function Be(e, r) {
197
+ const t = typeof e == "string" ? e : e instanceof URL ? e.href : e.url, n = re.get(t);
47
198
  if (n !== void 0)
48
199
  return Promise.resolve(new Response(n, { status: 200 }));
49
200
  let o;
@@ -52,30 +203,30 @@ function ge(e, r) {
52
203
  } catch {
53
204
  o = "";
54
205
  }
55
- const s = X.get(o);
56
- return s !== void 0 ? ye(s, t) : M(e, r);
206
+ const s = B.get(o);
207
+ return s !== void 0 ? Ce(s, t) : L(e, r);
57
208
  }
58
- const ve = '<?xml version="1.0"?><pretext-preview-missing-file/>';
59
- async function ye(e, r) {
60
- const t = decodeURIComponent(new URL(r).pathname), n = await te(e, t);
209
+ const Me = '<?xml version="1.0"?><pretext-preview-missing-file/>';
210
+ async function Ce(e, r) {
211
+ const t = decodeURIComponent(new URL(r).pathname), n = await ne(e, t);
61
212
  if (n === void 0)
62
- return new Response(ve, { status: 200 });
213
+ return new Response(Me, { status: 200 });
63
214
  const o = typeof n == "string" ? n : new Uint8Array(n);
64
215
  return new Response(o, { status: 200 });
65
216
  }
66
- function re() {
67
- M || (M = globalThis.fetch, globalThis.fetch = ge);
217
+ function oe() {
218
+ L || (L = globalThis.fetch, globalThis.fetch = Be);
68
219
  }
69
- function ne(e) {
70
- re();
71
- const r = `mnt${++be}.ptx.invalid`;
72
- return X.set(r, e), `http://${r}`;
220
+ function se(e) {
221
+ oe();
222
+ const r = `mnt${++je}.ptx.invalid`;
223
+ return B.set(r, e), `http://${r}`;
73
224
  }
74
- function xe(e) {
75
- X.delete(new URL(e).host);
225
+ function Xe(e) {
226
+ B.delete(new URL(e).host);
76
227
  }
77
- function Te(e, r) {
78
- re(), ee.set(e, r);
228
+ function Fe(e, r) {
229
+ oe(), re.set(e, r);
79
230
  }
80
231
  const R = `<?xml version="1.0" encoding="UTF-8"?>
81
232
  <publication>
@@ -86,7 +237,7 @@ const R = `<?xml version="1.0" encoding="UTF-8"?>
86
237
  <platform portable="yes"/>
87
238
  </html>
88
239
  </publication>
89
- `, Ee = ["theme", "style", "shell"];
240
+ `, _e = ["theme", "style", "shell"];
90
241
  function w(e, r) {
91
242
  for (const t of e.children)
92
243
  if (t.type === "element" && t.name === r)
@@ -96,21 +247,21 @@ function g(e, r) {
96
247
  let t = w(e, r);
97
248
  return t || (t = { type: "element", name: r, attributes: {}, children: [] }, e.children.push(t)), t;
98
249
  }
99
- function $e(e, r) {
250
+ function Oe(e, r) {
100
251
  const t = w(e, "css");
101
- if (t && Ee.some((o) => t.attributes?.[o]))
252
+ if (t && _e.some((o) => t.attributes?.[o]))
102
253
  return;
103
254
  const n = t ?? g(e, "css");
104
255
  n.attributes = { ...n.attributes, theme: r };
105
256
  }
106
- function Se(e, r) {
257
+ function We(e, r) {
107
258
  const t = w(e, "appearance");
108
259
  if (t?.attributes?.theme)
109
260
  return;
110
261
  const n = t ?? g(e, "appearance");
111
262
  n.attributes = { ...n.attributes, theme: r };
112
263
  }
113
- function Pe(e) {
264
+ function Ue(e) {
114
265
  const r = g(e, "resources");
115
266
  r.attributes = {
116
267
  ...r.attributes,
@@ -118,30 +269,30 @@ function Pe(e) {
118
269
  math: "online"
119
270
  };
120
271
  }
121
- function ke(e, r = {}) {
272
+ function Ne(e, r = {}) {
122
273
  const t = r.cssTheme?.trim(), n = r.revealTheme?.trim(), o = r.target === "slides";
123
274
  if (!e && !t && !o)
124
275
  return R;
125
- const s = x(e ?? R), a = w(s, "publication");
276
+ const s = y(e ?? R), a = w(s, "publication");
126
277
  if (!a)
127
278
  throw new Error(
128
279
  "Invalid publication file: no root <publication> element found"
129
280
  );
130
281
  const i = g(a, "html"), u = g(i, "platform");
131
- if (u.attributes = { ...u.attributes, portable: "yes" }, t && $e(i, t), o) {
282
+ if (u.attributes = { ...u.attributes, portable: "yes" }, t && Oe(i, t), o) {
132
283
  const c = g(a, "revealjs");
133
- Pe(c), n && Se(c, n);
284
+ Ue(c), n && We(c, n);
134
285
  }
135
286
  return $(s);
136
287
  }
137
- function H(e) {
288
+ function J(e) {
138
289
  if (!(e === void 0 || e === "" || e.startsWith("/")))
139
290
  return e.endsWith("/") ? e : `${e}/`;
140
291
  }
141
- function De(e) {
142
- const r = x(e ?? R), t = w(r, "publication"), n = t && w(t, "source"), o = n && w(n, "directories"), s = H(
292
+ function He(e) {
293
+ const r = y(e ?? R), t = w(r, "publication"), n = t && w(t, "source"), o = n && w(n, "directories"), s = J(
143
294
  o?.attributes?.external ?? void 0
144
- ), a = H(
295
+ ), a = J(
145
296
  o?.attributes?.generated ?? void 0
146
297
  );
147
298
  return {
@@ -150,15 +301,15 @@ function De(e) {
150
301
  managed: s !== void 0 && a !== void 0
151
302
  };
152
303
  }
153
- const oe = "http://www.w3.org/2001/XInclude", N = 64;
154
- async function Ie(e, r, t) {
155
- return e.includes("include") ? (await se(e, r, t)).content : e;
304
+ const ie = "http://www.w3.org/2001/XInclude", K = 64;
305
+ async function Je(e, r, t) {
306
+ return e.includes("include") ? (await ae(e, r, t)).content : e;
156
307
  }
157
- async function se(e, r, t) {
158
- const n = x(e), o = {
308
+ async function ae(e, r, t) {
309
+ const n = y(e), o = {
159
310
  projectDir: l.resolve(t),
160
311
  stack: [l.resolve(r)]
161
- }, s = await y(
312
+ }, s = await x(
162
313
  n,
163
314
  l.dirname(l.resolve(r)),
164
315
  { "": "" },
@@ -166,10 +317,10 @@ async function se(e, r, t) {
166
317
  );
167
318
  return { tree: n, content: s ? $(n) : e };
168
319
  }
169
- function Me(e) {
320
+ function Ke(e) {
170
321
  return e.data?.ptxIncludedFile;
171
322
  }
172
- function Re(e, r) {
323
+ function ze(e, r) {
173
324
  const t = e.data ?? (e.data = {});
174
325
  t.ptxIncludedFile = r;
175
326
  }
@@ -179,30 +330,30 @@ function S(e, r) {
179
330
  (n === "xmlns" || n.startsWith("xmlns:")) && (t === e && (t = { ...e }), t[n === "xmlns" ? "" : n.slice(6)] = o ?? "");
180
331
  return t;
181
332
  }
182
- function ie(e, r) {
333
+ function ce(e, r) {
183
334
  const t = e.name.indexOf(":"), n = t === -1 ? "" : e.name.slice(0, t);
184
- return (t === -1 ? e.name : e.name.slice(t + 1)) === "include" && r[n] === oe;
335
+ return (t === -1 ? e.name : e.name.slice(t + 1)) === "include" && r[n] === ie;
185
336
  }
186
- async function y(e, r, t, n) {
337
+ async function x(e, r, t, n) {
187
338
  let o = !1;
188
339
  for (let s = 0; s < e.children.length; s++) {
189
340
  const a = e.children[s];
190
341
  if (a.type !== "element")
191
342
  continue;
192
343
  const i = S(t, a);
193
- if (ie(a, i)) {
194
- const u = await ae(
344
+ if (ce(a, i)) {
345
+ const u = await le(
195
346
  a,
196
347
  r,
197
348
  i,
198
349
  n
199
350
  );
200
351
  e.children.splice(s, 1, ...u), s += u.length - 1, o = !0;
201
- } else await y(a, r, i, n) && (o = !0);
352
+ } else await x(a, r, i, n) && (o = !0);
202
353
  }
203
354
  return o;
204
355
  }
205
- async function ae(e, r, t, n) {
356
+ async function le(e, r, t, n) {
206
357
  const o = n.stack[n.stack.length - 1];
207
358
  if (e.attributes.xpointer)
208
359
  throw new Error(
@@ -225,44 +376,44 @@ async function ae(e, r, t, n) {
225
376
  throw new Error(
226
377
  `Circular xi:include: ${[...n.stack, i].join(" -> ")}`
227
378
  );
228
- if (n.stack.length >= N)
229
- throw new Error(`xi:include nesting exceeds ${N} levels`);
379
+ if (n.stack.length >= K)
380
+ throw new Error(`xi:include nesting exceeds ${K} levels`);
230
381
  const u = await j(i);
231
382
  if (u === void 0) {
232
- const h = je(e, t);
233
- if (h)
234
- return await y(h, r, t, n), h.children;
383
+ const p = qe(e, t);
384
+ if (p)
385
+ return await x(p, r, t, n), p.children;
235
386
  throw new Error(`xi:include target not found: ${s} (in ${o})`);
236
387
  }
237
388
  if (e.attributes.parse === "text")
238
389
  return [{ type: "text", value: u }];
239
390
  let c;
240
391
  try {
241
- c = x(u);
242
- } catch (h) {
392
+ c = y(u);
393
+ } catch (p) {
243
394
  throw new Error(
244
- `Could not parse xi:include target ${i} as XML: ${h instanceof Error ? h.message : h}. (Included files must be well-formed, with a single root element.)`
395
+ `Could not parse xi:include target ${i} as XML: ${p instanceof Error ? p.message : p}. (Included files must be well-formed, with a single root element.)`
245
396
  );
246
397
  }
247
398
  n.stack.push(i);
248
399
  try {
249
- await y(c, l.dirname(i), { "": "" }, n);
400
+ await x(c, l.dirname(i), { "": "" }, n);
250
401
  } finally {
251
402
  n.stack.pop();
252
403
  }
253
404
  const f = c.children.filter(
254
- (h) => h.type === "element"
405
+ (p) => p.type === "element"
255
406
  );
256
- for (const h of f)
257
- Re(h, i);
407
+ for (const p of f)
408
+ ze(p, i);
258
409
  return f;
259
410
  }
260
- function J(e) {
411
+ function z(e) {
261
412
  return e.name === "docinfo";
262
413
  }
263
- async function Ae(e, r, t) {
414
+ async function Ye(e, r, t) {
264
415
  try {
265
- const o = x(e).children.find(
416
+ const o = y(e).children.find(
266
417
  (c) => c.type === "element"
267
418
  );
268
419
  if (!o)
@@ -275,16 +426,16 @@ async function Ae(e, r, t) {
275
426
  if (c.type !== "element")
276
427
  continue;
277
428
  const f = S(u, c);
278
- if (J(c))
279
- return await y(c, a, f, i), $(c);
280
- if (ie(c, f)) {
281
- const m = (await ae(
429
+ if (z(c))
430
+ return await x(c, a, f, i), $(c);
431
+ if (ce(c, f)) {
432
+ const m = (await le(
282
433
  c,
283
434
  a,
284
435
  f,
285
436
  i
286
437
  )).find(
287
- (p) => p.type === "element" && J(p)
438
+ (h) => h.type === "element" && z(h)
288
439
  );
289
440
  if (m)
290
441
  return $(m);
@@ -297,33 +448,33 @@ async function Ae(e, r, t) {
297
448
  return;
298
449
  }
299
450
  }
300
- function je(e, r) {
451
+ function qe(e, r) {
301
452
  for (const t of e.children) {
302
453
  if (t.type !== "element")
303
454
  continue;
304
455
  const n = S(r, t), o = t.name.indexOf(":"), s = o === -1 ? "" : t.name.slice(0, o);
305
- if ((o === -1 ? t.name : t.name.slice(o + 1)) === "fallback" && n[s] === oe)
456
+ if ((o === -1 ? t.name : t.name.slice(o + 1)) === "fallback" && n[s] === ie)
306
457
  return t;
307
458
  }
308
459
  }
309
- function ce(e) {
460
+ function ue(e) {
310
461
  return typeof e == "object" && e !== null && e.type === "element";
311
462
  }
312
- function Xe(e) {
463
+ function Ge(e) {
313
464
  return /^(pf|xhtml):/.test(e.name);
314
465
  }
315
- function Le(e, r, t) {
316
- const n = [], o = e.children.find(ce);
466
+ function Ve(e, r, t) {
467
+ const n = [], o = e.children.find(ue);
317
468
  if (o) {
318
469
  const s = t?.parentId ?? "root";
319
- le(o, s, t?.position ?? 1, r, s, n);
470
+ de(o, s, t?.position ?? 1, r, s, n);
320
471
  }
321
472
  return n;
322
473
  }
323
- function le(e, r, t, n, o, s) {
324
- const a = Me(e) ?? n;
474
+ function de(e, r, t, n, o, s) {
475
+ const a = Ke(e) ?? n;
325
476
  let i, u;
326
- if (Xe(e))
477
+ if (Ge(e))
327
478
  u = "root";
328
479
  else {
329
480
  const f = e.attributes.label ?? e.attributes["xml:id"];
@@ -338,7 +489,7 @@ function le(e, r, t, n, o, s) {
338
489
  }
339
490
  let c = 0;
340
491
  for (const f of e.children)
341
- ce(f) && (c += 1, le(
492
+ ue(f) && (c += 1, de(
342
493
  f,
343
494
  u,
344
495
  c,
@@ -347,48 +498,48 @@ function le(e, r, t, n, o, s) {
347
498
  s
348
499
  ));
349
500
  }
350
- function at(e, r) {
501
+ function Tt(e, r) {
351
502
  let t;
352
503
  for (const n of e)
353
504
  n.line <= r && (t = n);
354
505
  return t ?? e[0];
355
506
  }
356
- function Fe(e) {
507
+ function Ze(e) {
357
508
  const r = e.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, " ");
358
509
  return /<\s*slide(?:show)?[\s/>]/.test(r) ? "slides" : "html";
359
510
  }
360
- function Ce() {
361
- return we(I(), "xsl");
511
+ function Qe() {
512
+ return Pe(I(), "xsl");
362
513
  }
363
- function Ue() {
514
+ function et() {
364
515
  return "Suspending" in WebAssembly;
365
516
  }
366
- function We() {
367
- if (!Ue())
517
+ function tt() {
518
+ if (!et())
368
519
  throw new Error(
369
520
  "WebAssembly JSPI is not enabled. Run Node with --experimental-wasm-jspi (or use the pretext-html CLI, which re-launches itself with the flag)."
370
521
  );
371
522
  }
372
- function z(e) {
523
+ function Y(e) {
373
524
  return e.includes("'") ? e.includes('"') ? `concat(${e.split("'").map((t) => `'${t}'`).join(`, "'", `)})` : `"${e}"` : `'${e}'`;
374
525
  }
375
- function Be(e) {
526
+ function rt(e) {
376
527
  return e.replace(
377
528
  /from '\.\/(https:\/\/[^']+)'/g,
378
529
  (r, t) => `from '${t}'`
379
530
  );
380
531
  }
381
- const _e = "https://cdn.jsdelivr.net/gh/PreTeXtBook/html-static@latest/dist/";
382
- function Oe(e) {
532
+ const nt = "https://cdn.jsdelivr.net/gh/PreTeXtBook/html-static@latest/dist/";
533
+ function ot(e) {
383
534
  return e.replace(
384
535
  /(<link\b[^>]*\bhref=["'])_static\//gi,
385
- `$1${_e}_static/`
536
+ `$1${nt}_static/`
386
537
  );
387
538
  }
388
- function He(e) {
539
+ function st(e) {
389
540
  return e.slice(0, 65536).replace(/<\?[\s\S]*?\?>/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<!DOCTYPE[^>]*>/gi, " ").match(/<\s*([A-Za-z][\w:-]*)/)?.[1];
390
541
  }
391
- async function V(e) {
542
+ async function q(e) {
392
543
  const r = await j(e);
393
544
  if (r === void 0)
394
545
  throw new Error(
@@ -396,12 +547,12 @@ async function V(e) {
396
547
  );
397
548
  return r;
398
549
  }
399
- async function Ne(e, r) {
550
+ async function it(e, r) {
400
551
  const t = l.resolve(e), n = await j(t);
401
552
  if (n !== void 0)
402
- return Ae(n, t, r);
553
+ return Ye(n, t, r);
403
554
  }
404
- function Je(e, r, t, n) {
555
+ function at(e, r, t, n) {
405
556
  const o = e.replace(/^\uFEFF/, "").replace(/<\?xml[\s\S]*?\?>/, "").replace(/<!DOCTYPE[^>]*>/i, ""), s = t === "slides" ? "slideshow" : r === "chapter" || r === "part" ? "book" : "article";
406
557
  return `<pretext>
407
558
  ${n?.trim() ? `${n.trim()}
@@ -412,50 +563,50 @@ ${o}
412
563
  </pretext>
413
564
  `;
414
565
  }
415
- let ue = !1;
416
- function ze(e) {
566
+ let fe = !1;
567
+ function ct(e) {
417
568
  return e instanceof Error && /\bAborted\(/.test(e.message);
418
569
  }
419
- function Ve(e) {
570
+ function lt(e) {
420
571
  return e instanceof Error && /memory access|out of bounds/i.test(e.message);
421
572
  }
422
- function Ye() {
423
- if (ue)
573
+ function ut() {
574
+ if (fe)
424
575
  throw new Error(
425
576
  "The WebAssembly renderer aborted earlier in this process and cannot be reused. Restart the process (or reload the page) to render again."
426
577
  );
427
578
  }
428
- function Y(e) {
429
- if (ze(e))
430
- throw ue = !0, new Error(
579
+ function G(e) {
580
+ if (ct(e))
581
+ throw fe = !0, new Error(
431
582
  "The WebAssembly renderer aborted and cannot be reused. Restart the process (or reload the page) to render again.",
432
583
  { cause: e }
433
584
  );
434
- if (Ve(e))
585
+ if (lt(e))
435
586
  throw new Error(
436
587
  "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.",
437
588
  { cause: e }
438
589
  );
439
590
  }
440
- let k;
441
- async function de() {
442
- return k || (k = (async () => {
591
+ let P;
592
+ async function pe() {
593
+ return P || (P = (async () => {
443
594
  const [e, r] = await Promise.all([
444
595
  import("@pretextbook/libxslt-wasm"),
445
596
  import("@pretextbook/libxslt-wasm/exslt")
446
597
  ]);
447
598
  return r.registerAll(), e;
448
- })()), k;
599
+ })()), P;
449
600
  }
450
- const D = /* @__PURE__ */ new Map(), qe = {
601
+ const D = /* @__PURE__ */ new Map(), dt = {
451
602
  html: "preview-html.xsl",
452
603
  slides: "preview-revealjs.xsl"
453
604
  };
454
- async function Ge(e, r) {
455
- const t = qe[r], n = `${r}\0${e}`;
605
+ async function ft(e, r) {
606
+ const t = dt[r], n = `${r}\0${e}`;
456
607
  let o = D.get(n);
457
608
  return o || (o = (async () => {
458
- const { XmlDocument: s, XsltStylesheet: a } = await de(), i = ne(e), u = await Q(I(), `/${t}`);
609
+ const { XmlDocument: s, XsltStylesheet: a } = await pe(), i = se(e), u = await ee(I(), `/${t}`);
459
610
  if (u === void 0)
460
611
  throw new Error(
461
612
  `Could not read ${t} from ${I()}. Check the assets location (PRETEXT_HTML_ASSETS under Node, setAssetsBase() in the browser).`
@@ -467,20 +618,20 @@ async function Ge(e, r) {
467
618
  return a.fromXmlDocument(f);
468
619
  })(), D.set(n, o), o.catch(() => D.delete(n))), o;
469
620
  }
470
- let q = Promise.resolve();
471
- function Ze(e) {
472
- const r = q.then(
473
- () => G(e),
474
- () => G(e)
621
+ let V = Promise.resolve();
622
+ function pt(e) {
623
+ const r = V.then(
624
+ () => Z(e),
625
+ () => Z(e)
475
626
  );
476
- return q = r.catch(() => {
627
+ return V = r.catch(() => {
477
628
  }), r;
478
629
  }
479
- async function G(e) {
480
- We(), Ye();
481
- const { XmlDocument: r } = await de(), t = l.resolve(e.sourcePath), n = l.resolve(
630
+ async function Z(e) {
631
+ tt(), ut();
632
+ const { XmlDocument: r } = await pe(), t = l.resolve(e.sourcePath), n = l.resolve(
482
633
  e.projectDir ?? l.dirname(t)
483
- ), o = e.sourceContent ?? await V(t), s = l.relative(n, t);
634
+ ), o = e.sourceContent ?? await q(t), s = l.relative(n, t);
484
635
  if (s.startsWith(".."))
485
636
  throw new Error(
486
637
  `sourcePath (${t}) must live inside projectDir (${n})`
@@ -488,92 +639,92 @@ async function G(e) {
488
639
  const a = l.relative(
489
640
  n,
490
641
  l.resolve(e.mainSourcePath ?? t)
491
- ), i = a.startsWith("..") ? s : a, u = ne(n);
642
+ ), i = a.startsWith("..") ? s : a, u = se(n);
492
643
  try {
493
644
  let c, f = `${u}/__pretext-preview-publication.xml`;
494
645
  if (e.publicationPath) {
495
646
  const d = l.resolve(e.publicationPath);
496
- c = await V(d);
647
+ c = await q(d);
497
648
  const v = l.relative(n, d);
498
649
  v.startsWith("..") || (f = `${u}/${v.split(l.sep).join("/")}`);
499
650
  }
500
- let h, m;
651
+ let p, m;
501
652
  if (e.sourceMap) {
502
- const d = await se(
653
+ const d = await ae(
503
654
  o,
504
655
  t,
505
656
  n
506
657
  );
507
- h = d.tree, m = d.content;
658
+ p = d.tree, m = d.content;
508
659
  } else
509
- m = await Ie(
660
+ m = await Je(
510
661
  o,
511
662
  t,
512
663
  n
513
664
  );
514
- const p = e.target ?? Fe(m), fe = await Ge(e.xslDir ?? Ce(), p), L = ke(c, {
665
+ const h = e.target ?? Ze(m), me = await ft(e.xslDir ?? Qe(), h), M = Ne(c, {
515
666
  cssTheme: e.cssTheme,
516
667
  revealTheme: e.revealTheme,
517
- target: p
668
+ target: h
518
669
  });
519
- Te(f, L);
520
- const T = De(L), F = l.dirname(l.resolve(n, i)), C = T.external !== void 0 && T.generated !== void 0 ? {
521
- external: l.resolve(F, T.external),
522
- generated: l.resolve(F, T.generated)
523
- } : void 0, E = He(m);
524
- let U = { parentId: "root", position: 1 };
525
- if (E !== "pretext" && E !== "mathbook")
670
+ Fe(f, M);
671
+ const E = He(M), C = l.dirname(l.resolve(n, i)), X = E.external !== void 0 && E.generated !== void 0 ? {
672
+ external: l.resolve(C, E.external),
673
+ generated: l.resolve(C, E.generated)
674
+ } : void 0, T = st(m);
675
+ let F = { parentId: "root", position: 1 };
676
+ if (T !== "pretext" && T !== "mathbook")
526
677
  if (e.fragment) {
527
- const d = e.docinfo ?? (e.docinfoSourcePath ? await Ne(e.docinfoSourcePath, n) : void 0);
528
- m = Je(
678
+ const d = e.docinfo ?? (e.docinfoSourcePath ? await it(e.docinfoSourcePath, n) : void 0);
679
+ m = at(
529
680
  m,
530
- E,
531
- p,
681
+ T,
682
+ h,
532
683
  d
533
- ), U = { parentId: d?.trim() ? "root-1-2" : "root-1-1", position: 2 };
684
+ ), F = { parentId: d?.trim() ? "root-1-2" : "root-1-1", position: 2 };
534
685
  } else
535
686
  throw new Error(
536
- `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.`
687
+ `The document root is <${T ?? "?"}>, not <pretext> — this looks like an xi:included fragment. Render the project's main source file instead, or pass the fragment option.`
537
688
  );
538
- const W = h ? Le(h, t, U) : void 0, B = await r.fromString(m, {
689
+ const _ = p ? Ve(p, t, F) : void 0, O = await r.fromString(m, {
539
690
  url: `${u}/${i.split(l.sep).join("/")}`,
540
691
  options: { noEnt: !0, dtdLoad: !0, huge: !0 }
541
- }), _ = {
542
- publisher: z(f)
692
+ }), W = {
693
+ publisher: Y(f)
543
694
  };
544
695
  for (const [d, v] of Object.entries(e.stringParams ?? {}))
545
- _[d] = z(v);
546
- let P;
696
+ W[d] = Y(v);
697
+ let k;
547
698
  try {
548
- P = await fe.apply(B, _);
699
+ k = await me.apply(O, W);
549
700
  } catch (d) {
550
- throw Y(d), new Error(
701
+ throw G(d), new Error(
551
702
  "PreTeXt XSLT transform failed; see the PTX:ERROR/PTX:FATAL messages on stderr for details.",
552
703
  { cause: d }
553
704
  );
554
705
  } finally {
555
- B.delete();
706
+ O.delete();
556
707
  }
557
708
  try {
558
- let d = Be(P.toHtmlString());
559
- return p === "slides" ? (d = Oe(d), d = me(d, e.revealView ?? "scroll", {
709
+ let d = rt(k.toHtmlString());
710
+ return (e.openKnowls ?? !0) && (d = Ae(d)), h === "slides" ? (d = ot(d), d = we(d, e.revealView ?? "scroll", {
560
711
  zoom: e.revealZoom
561
- })) : e.theme && (d = pe(d, e.theme)), {
712
+ })) : e.theme && (d = be(d, e.theme)), e.previewBanner && (d = ke(d, e.previewBanner)), {
562
713
  html: d,
563
- target: p,
564
- ...W ? { sourceMap: W } : {},
565
- ...C ? { assetDirs: C } : {}
714
+ target: h,
715
+ ..._ ? { sourceMap: _ } : {},
716
+ ...X ? { assetDirs: X } : {}
566
717
  };
567
718
  } catch (d) {
568
- throw Y(d), d;
719
+ throw G(d), d;
569
720
  } finally {
570
- P.delete();
721
+ k.delete();
571
722
  }
572
723
  } finally {
573
- xe(u);
724
+ Xe(u);
574
725
  }
575
726
  }
576
- const Z = `Usage: pretext-html <source.ptx> [options]
727
+ const Q = `Usage: pretext-html <source.ptx> [options]
577
728
 
578
729
  Render a PreTeXt document to a single standalone HTML page (portable build:
579
730
  one page, css/js/MathJax from CDN). No PreTeXt installation required.
@@ -600,9 +751,13 @@ Options:
600
751
  xi:includes (used when --docinfo is not given)
601
752
  --source-map <file> Also write a JSON source map: HTML id → source
602
753
  file/line for every element (for editor sync)
754
+ --no-open-knowls Leave solutions, hints and other born-hidden
755
+ knowls collapsed, as a real PreTeXt build does.
756
+ They are expanded by default, since these pages
757
+ are previews of work in progress
603
758
  -h, --help Show this help
604
759
  `;
605
- function Qe(e) {
760
+ function mt(e) {
606
761
  let r, t, n, o;
607
762
  const s = {}, a = {};
608
763
  for (let i = 0; i < e.length; i++) {
@@ -614,7 +769,7 @@ function Qe(e) {
614
769
  switch (u) {
615
770
  case "-h":
616
771
  case "--help":
617
- b.stdout.write(Z), b.exit(0);
772
+ b.stdout.write(Q), b.exit(0);
618
773
  break;
619
774
  case "-o":
620
775
  case "--output":
@@ -635,6 +790,9 @@ function Qe(e) {
635
790
  case "--fragment":
636
791
  s.fragment = !0;
637
792
  break;
793
+ case "--no-open-knowls":
794
+ s.openKnowls = !1;
795
+ break;
638
796
  case "--docinfo":
639
797
  n = c();
640
798
  break;
@@ -645,10 +803,10 @@ function Qe(e) {
645
803
  o = c(), s.sourceMap = !0;
646
804
  break;
647
805
  case "--param": {
648
- const f = c(), h = f.indexOf("=");
649
- if (h === -1)
806
+ const f = c(), p = f.indexOf("=");
807
+ if (p === -1)
650
808
  throw new Error(`--param expects name=value, got: ${f}`);
651
- a[f.slice(0, h)] = f.slice(h + 1);
809
+ a[f.slice(0, p)] = f.slice(p + 1);
652
810
  break;
653
811
  }
654
812
  default:
@@ -662,7 +820,7 @@ function Qe(e) {
662
820
  if (!r)
663
821
  throw new Error(`No source file given.
664
822
 
665
- ` + Z);
823
+ ` + Q);
666
824
  return Object.keys(a).length > 0 && (s.stringParams = a), {
667
825
  options: { ...s, sourcePath: r },
668
826
  output: t,
@@ -670,25 +828,29 @@ function Qe(e) {
670
828
  sourceMapPath: o
671
829
  };
672
830
  }
673
- async function ct(e) {
674
- const { options: r, output: t, docinfoPath: n, sourceMapPath: o } = Qe(e);
831
+ async function $t(e) {
832
+ const { options: r, output: t, docinfoPath: n, sourceMapPath: o } = mt(e);
675
833
  n && (r.docinfo = await A(n, "utf8"));
676
- const s = Date.now(), { html: a, sourceMap: i } = await Ze(r);
834
+ const s = Date.now(), { html: a, sourceMap: i } = await pt(r);
677
835
  b.stderr.write(`pretext-html: rendered in ${Date.now() - s}ms
678
- `), o && i && (await O(o, JSON.stringify(i, null, 2)), b.stderr.write(`pretext-html: wrote ${o}
679
- `)), t ? (await O(t, a), b.stderr.write(`pretext-html: wrote ${t}
836
+ `), o && i && (await U(o, JSON.stringify(i, null, 2)), b.stderr.write(`pretext-html: wrote ${o}
837
+ `)), t ? (await U(t, a), b.stderr.write(`pretext-html: wrote ${t}
680
838
  `)) : b.stdout.write(a);
681
839
  }
682
840
  export {
683
- Fe as a,
684
- ke as b,
685
- it as c,
686
- Ce as d,
687
- at as f,
688
- Ue as i,
689
- ct as m,
690
- Qe as p,
691
- Ze as r,
692
- st as s,
693
- z as x
841
+ ge as P,
842
+ Ze as a,
843
+ Ne as b,
844
+ et as c,
845
+ Qe as d,
846
+ Et as e,
847
+ Tt as f,
848
+ mt as g,
849
+ ke as i,
850
+ $t as m,
851
+ Ae as o,
852
+ Ee as p,
853
+ pt as r,
854
+ yt as s,
855
+ Y as x
694
856
  };