@pretextbook/pretext-html 0.10.1 → 0.12.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.
@@ -1,26 +1,27 @@
1
- import { readFile as W, writeFile as Z } from "node:fs/promises";
2
- import * as y from "node:process";
3
- import * as u from "node:path";
4
- import { fileURLToPath as Ae } from "node:url";
1
+ import { readFile as W, writeFile as Q } from "node:fs/promises";
2
+ import * as b from "node:process";
3
+ import { listPrintouts as je, rootPrintoutId as Me, injectPrintPreview as fe } from "./printout.js";
4
+ import * as f from "node:path";
5
+ import { fileURLToPath as _e } from "node:url";
5
6
  import { fromXml as E } from "xast-util-from-xml";
6
7
  import { toXml as I } from "xast-util-to-xml";
7
- import { injectRevealBridge as Le } from "./reveal.js";
8
- import { injectThemeBridge as Me } from "./theme.js";
9
- const _e = "ptxPreviewBannerDismissed", je = "About live preview";
10
- function Q(e) {
8
+ import { injectRevealBridge as Be } from "./reveal.js";
9
+ import { injectThemeBridge as Oe } from "./theme.js";
10
+ const Ce = "ptxPreviewBannerDismissed", Fe = "About live preview";
11
+ function ee(e) {
11
12
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
12
13
  }
13
- function Be(e) {
14
+ function Ne(e) {
14
15
  return [
15
16
  '<div id="ptx-preview-banner" class="ptx-preview-banner" role="note">',
16
- ` <span class="ptx-preview-banner-text">${Q(e)}</span>`,
17
+ ` <span class="ptx-preview-banner-text">${ee(e)}</span>`,
17
18
  ' <button type="button" class="ptx-preview-banner-dismiss" aria-label="Dismiss">&times;</button>',
18
19
  "</div>",
19
- `<button type="button" id="ptx-preview-banner-restore" class="ptx-preview-banner-restore" hidden>${Q(je)}</button>`
20
+ `<button type="button" id="ptx-preview-banner-restore" class="ptx-preview-banner-restore" hidden>${ee(Fe)}</button>`
20
21
  ].join(`
21
22
  `);
22
23
  }
23
- function Oe() {
24
+ function Xe() {
24
25
  return [
25
26
  "<style>",
26
27
  ".ptx-preview-banner {",
@@ -77,15 +78,23 @@ function Oe() {
77
78
  ".ptx-preview-banner-restore:hover {",
78
79
  " opacity: 0.85;",
79
80
  "}",
81
+ // Printing a preview is a real workflow — the print-preview layout exists
82
+ // to be printed from (see printout.ts) — and a warning about the preview
83
+ // has no business on the paper.
84
+ "@media print {",
85
+ " .ptx-preview-banner, .ptx-preview-banner-restore {",
86
+ " display: none !important;",
87
+ " }",
88
+ "}",
80
89
  "</style>"
81
90
  ].join(`
82
91
  `);
83
92
  }
84
- function Ce() {
93
+ function Ue() {
85
94
  return [
86
95
  "<script>",
87
96
  "(function () {",
88
- " var KEY = " + JSON.stringify(_e) + ";",
97
+ " var KEY = " + JSON.stringify(Ce) + ";",
89
98
  ' var banner = document.getElementById("ptx-preview-banner");',
90
99
  ' var restore = document.getElementById("ptx-preview-banner-restore");',
91
100
  " if (!banner || !restore) { return; }",
@@ -122,22 +131,22 @@ function Ce() {
122
131
  ].join(`
123
132
  `);
124
133
  }
125
- const Fe = "<!--ptx-preview-banner-->", Ne = "<!--/ptx-preview-banner-->", Xe = /\n?<!--ptx-preview-banner-->[\s\S]*?<!--\/ptx-preview-banner-->/;
126
- function Ue(e, r) {
127
- const t = Xe.exec(e), n = t ? e.slice(0, t.index) + e.slice(t.index + t[0].length) : e;
134
+ const We = "<!--ptx-preview-banner-->", He = "<!--/ptx-preview-banner-->", Je = /\n?<!--ptx-preview-banner-->[\s\S]*?<!--\/ptx-preview-banner-->/;
135
+ function ze(e, r) {
136
+ const t = Je.exec(e), n = t ? e.slice(0, t.index) + e.slice(t.index + t[0].length) : e;
128
137
  if (!/<body[^>]*>/i.test(n))
129
138
  return n;
130
139
  const o = `
131
- ${Fe}
132
- ${Oe()}
133
- ${Be(r.message)}
134
- ${Ce()}
135
- ${Ne}`;
140
+ ${We}
141
+ ${Xe()}
142
+ ${Ne(r.message)}
143
+ ${Ue()}
144
+ ${He}`;
136
145
  return n.replace(/<body([^>]*)>/i, `<body$1>${o}`);
137
146
  }
138
- async function de(e, r) {
139
- const t = u.resolve(e), n = u.resolve(t, `.${u.posix.normalize(r)}`);
140
- if (n !== t && !n.startsWith(t + u.sep)) {
147
+ async function pe(e, r) {
148
+ const t = f.resolve(e), n = f.resolve(t, `.${f.posix.normalize(r)}`);
149
+ if (n !== t && !n.startsWith(t + f.sep)) {
141
150
  console.error(
142
151
  `pretext-html: refusing to serve ${r} from outside ${t}`
143
152
  );
@@ -149,59 +158,59 @@ async function de(e, r) {
149
158
  return;
150
159
  }
151
160
  }
152
- async function M(e) {
161
+ async function j(e) {
153
162
  try {
154
163
  return await W(e, "utf8");
155
164
  } catch {
156
165
  return;
157
166
  }
158
167
  }
159
- let fe;
160
- function en(e) {
161
- fe = e;
168
+ let he;
169
+ function sn(e) {
170
+ he = e;
162
171
  }
163
172
  function C() {
164
- return fe ?? process.env.PRETEXT_HTML_ASSETS ?? u.resolve(u.dirname(Ae(import.meta.url)), "..", "assets");
173
+ return he ?? process.env.PRETEXT_HTML_ASSETS ?? f.resolve(f.dirname(_e(import.meta.url)), "..", "assets");
165
174
  }
166
- function We(e, r) {
167
- return u.join(e, r);
175
+ function Ke(e, r) {
176
+ return f.join(e, r);
168
177
  }
169
- const pe = "2.49.1", He = "8.2.4", Je = [
178
+ const me = "2.49.1", Ve = "8.2.4", Ge = [
170
179
  "prefix-runtime.40bd1420d3277749.bundle.js",
171
180
  "prefix-926.5c7038c8ef173faf.bundle.js",
172
181
  "prefix-runestone.b388362b5f43738a.bundle.js"
173
- ], ze = [
182
+ ], Ye = [
174
183
  "prefix-926.229729d09512acc9.css",
175
184
  "prefix-runestone.8086b62682b271d1.css"
176
- ], Ke = "born-hidden-knowl", Ve = /<details\b([^>]*)>(\s*)(?:<summary\b([^>]*)>)?/g;
177
- function Ge(e) {
185
+ ], qe = "born-hidden-knowl", Ze = /<details\b([^>]*)>(\s*)(?:<summary\b([^>]*)>)?/g;
186
+ function Qe(e) {
178
187
  const r = /\bclass="([^"]*)"/.exec(e);
179
188
  return r ? r[1].trim().split(/\s+/) : [];
180
189
  }
181
- function Ye(e) {
190
+ function et(e) {
182
191
  return /(^|\s)open(\s|=|$)/.test(e);
183
192
  }
184
- function ee(e) {
185
- return Ye(e) ? e : ` open${e}`;
193
+ function te(e) {
194
+ return et(e) ? e : ` open${e}`;
186
195
  }
187
- function qe(e) {
196
+ function tt(e) {
188
197
  return e.replace(
189
- Ve,
198
+ Ze,
190
199
  (r, t, n, o) => {
191
- if (!Ge(t).includes(Ke))
200
+ if (!Qe(t).includes(qe))
192
201
  return r;
193
- const i = `<details${ee(t)}>`;
194
- return o === void 0 ? `${i}${n}` : `${i}${n}<summary${ee(o)}>`;
202
+ const i = `<details${te(t)}>`;
203
+ return o === void 0 ? `${i}${n}` : `${i}${n}<summary${te(o)}>`;
195
204
  }
196
205
  );
197
206
  }
198
- const H = /* @__PURE__ */ new Map(), me = /* @__PURE__ */ new Map();
199
- let F, Ze = 0, he = de;
200
- function tn(e) {
201
- he = e;
207
+ const H = /* @__PURE__ */ new Map(), we = /* @__PURE__ */ new Map();
208
+ let F, nt = 0, be = pe;
209
+ function an(e) {
210
+ be = e;
202
211
  }
203
- function Qe(e, r) {
204
- const t = typeof e == "string" ? e : e instanceof URL ? e.href : e.url, n = me.get(t);
212
+ function rt(e, r) {
213
+ const t = typeof e == "string" ? e : e instanceof URL ? e.href : e.url, n = we.get(t);
205
214
  if (n !== void 0)
206
215
  return Promise.resolve(new Response(n, { status: 200 }));
207
216
  let o;
@@ -211,64 +220,67 @@ function Qe(e, r) {
211
220
  o = "";
212
221
  }
213
222
  const i = H.get(o);
214
- return i !== void 0 ? tt(i, t) : F(e, r);
223
+ return i !== void 0 ? it(i, t) : F(e, r);
215
224
  }
216
- const et = '<?xml version="1.0"?><pretext-preview-missing-file/>';
217
- async function tt(e, r) {
218
- const t = decodeURIComponent(new URL(r).pathname), n = await he(e, t);
225
+ const ot = '<?xml version="1.0"?><pretext-preview-missing-file/>';
226
+ async function it(e, r) {
227
+ const t = decodeURIComponent(new URL(r).pathname), n = await be(e, t);
219
228
  if (n === void 0)
220
- return new Response(et, { status: 200 });
229
+ return new Response(ot, { status: 200 });
221
230
  const o = typeof n == "string" ? n : new Uint8Array(n);
222
231
  return new Response(o, { status: 200 });
223
232
  }
224
- function we() {
225
- F || (F = globalThis.fetch, globalThis.fetch = Qe);
233
+ function ve() {
234
+ F || (F = globalThis.fetch, globalThis.fetch = rt);
226
235
  }
227
- function be(e) {
228
- we();
229
- const r = `mnt${++Ze}.ptx.invalid`;
236
+ function ge(e) {
237
+ ve();
238
+ const r = `mnt${++nt}.ptx.invalid`;
230
239
  return H.set(r, e), `http://${r}`;
231
240
  }
232
- function nt(e) {
241
+ function st(e) {
233
242
  H.delete(new URL(e).host);
234
243
  }
235
- function rt(e, r) {
236
- we(), me.set(e, r);
244
+ function at(e, r) {
245
+ ve(), we.set(e, r);
237
246
  }
238
247
  const N = `<?xml version="1.0" encoding="UTF-8"?>
239
248
  <publication>
240
249
  <source>
241
250
  <directories external="../assets" generated="../generated-assets" />
242
251
  </source>
252
+ <common>
253
+ <tableofcontents level="0"/>
254
+ </common>
243
255
  <html>
244
256
  <platform portable="yes"/>
245
257
  </html>
246
258
  </publication>
247
- `, ot = ["theme", "style", "shell"];
248
- function x(e, r) {
259
+ `, ct = ["theme", "style", "shell"];
260
+ function y(e, r) {
249
261
  for (const t of e.children)
250
262
  if (t.type === "element" && t.name === r)
251
263
  return t;
252
264
  }
253
265
  function T(e, r) {
254
- let t = x(e, r);
266
+ let t = y(e, r);
255
267
  return t || (t = { type: "element", name: r, attributes: {}, children: [] }, e.children.push(t)), t;
256
268
  }
257
- function it(e, r) {
258
- const t = x(e, "css");
259
- if (t && ot.some((o) => t.attributes?.[o]))
269
+ function lt(e, r) {
270
+ const t = y(e, "css");
271
+ if (t && ct.some((o) => t.attributes?.[o]))
260
272
  return;
261
273
  const n = t ?? T(e, "css");
262
274
  n.attributes = { ...n.attributes, theme: r };
263
275
  }
264
- function st(e, r) {
265
- const t = x(e, "appearance");
276
+ function ut(e, r) {
277
+ const t = y(e, "appearance");
266
278
  if (t?.attributes?.theme)
267
279
  return;
268
280
  const n = t ?? T(e, "appearance");
269
281
  n.attributes = { ...n.attributes, theme: r };
270
282
  }
271
- function at(e) {
283
+ function dt(e) {
272
284
  const r = T(e, "resources");
273
285
  r.attributes = {
274
286
  ...r.attributes,
@@ -276,30 +288,30 @@ function at(e) {
276
288
  math: "online"
277
289
  };
278
290
  }
279
- function ct(e, r = {}) {
291
+ function ft(e, r = {}) {
280
292
  const t = r.cssTheme?.trim(), n = r.revealTheme?.trim(), o = r.target === "slides";
281
293
  if (!e && !t && !o)
282
294
  return N;
283
- const i = E(e ?? N), s = x(i, "publication");
295
+ const i = E(e ?? N), s = y(i, "publication");
284
296
  if (!s)
285
297
  throw new Error(
286
298
  "Invalid publication file: no root <publication> element found"
287
299
  );
288
- const a = T(s, "html"), l = T(a, "platform");
289
- if (l.attributes = { ...l.attributes, portable: "yes" }, t && it(a, t), o) {
290
- const c = T(s, "revealjs");
291
- at(c), n && st(c, n);
300
+ const a = T(s, "html"), c = T(a, "platform");
301
+ if (c.attributes = { ...c.attributes, portable: "yes" }, t && lt(a, t), o) {
302
+ const l = T(s, "revealjs");
303
+ dt(l), n && ut(l, n);
292
304
  }
293
305
  return I(i);
294
306
  }
295
- function te(e) {
307
+ function ne(e) {
296
308
  if (!(e === void 0 || e === "" || e.startsWith("/")))
297
309
  return e.endsWith("/") ? e : `${e}/`;
298
310
  }
299
- function lt(e) {
300
- const r = E(e ?? N), t = x(r, "publication"), n = t && x(t, "source"), o = n && x(n, "directories"), i = te(
311
+ function pt(e) {
312
+ const r = E(e ?? N), t = y(r, "publication"), n = t && y(t, "source"), o = n && y(n, "directories"), i = ne(
301
313
  o?.attributes?.external ?? void 0
302
- ), s = te(
314
+ ), s = ne(
303
315
  o?.attributes?.generated ?? void 0
304
316
  );
305
317
  return {
@@ -308,26 +320,26 @@ function lt(e) {
308
320
  managed: i !== void 0 && s !== void 0
309
321
  };
310
322
  }
311
- const ge = "http://www.w3.org/2001/XInclude", ne = 64;
312
- async function ut(e, r, t) {
323
+ const xe = "http://www.w3.org/2001/XInclude", re = 64;
324
+ async function ht(e, r, t) {
313
325
  return e.includes("include") ? (await J(e, r, t)).content : e;
314
326
  }
315
327
  async function J(e, r, t) {
316
328
  const n = E(e), o = {
317
- projectDir: u.resolve(t),
318
- stack: [u.resolve(r)]
319
- }, i = await P(
329
+ projectDir: f.resolve(t),
330
+ stack: [f.resolve(r)]
331
+ }, i = await R(
320
332
  n,
321
- u.dirname(u.resolve(r)),
333
+ f.dirname(f.resolve(r)),
322
334
  { "": "" },
323
335
  o
324
336
  );
325
337
  return { tree: n, content: i ? I(n) : e };
326
338
  }
327
- function dt(e) {
339
+ function mt(e) {
328
340
  return e.data?.ptxIncludedFile;
329
341
  }
330
- function ft(e, r) {
342
+ function wt(e, r) {
331
343
  const t = e.data ?? (e.data = {});
332
344
  t.ptxIncludedFile = r;
333
345
  }
@@ -337,30 +349,30 @@ function L(e, r) {
337
349
  (n === "xmlns" || n.startsWith("xmlns:")) && (t === e && (t = { ...e }), t[n === "xmlns" ? "" : n.slice(6)] = o ?? "");
338
350
  return t;
339
351
  }
340
- function ve(e, r) {
352
+ function ye(e, r) {
341
353
  const t = e.name.indexOf(":"), n = t === -1 ? "" : e.name.slice(0, t);
342
- return (t === -1 ? e.name : e.name.slice(t + 1)) === "include" && r[n] === ge;
354
+ return (t === -1 ? e.name : e.name.slice(t + 1)) === "include" && r[n] === xe;
343
355
  }
344
- async function P(e, r, t, n) {
356
+ async function R(e, r, t, n) {
345
357
  let o = !1;
346
358
  for (let i = 0; i < e.children.length; i++) {
347
359
  const s = e.children[i];
348
360
  if (s.type !== "element")
349
361
  continue;
350
362
  const a = L(t, s);
351
- if (ve(s, a)) {
352
- const l = await xe(
363
+ if (ye(s, a)) {
364
+ const c = await Te(
353
365
  s,
354
366
  r,
355
367
  a,
356
368
  n
357
369
  );
358
- e.children.splice(i, 1, ...l), i += l.length - 1, o = !0;
359
- } else await P(s, r, a, n) && (o = !0);
370
+ e.children.splice(i, 1, ...c), i += c.length - 1, o = !0;
371
+ } else await R(s, r, a, n) && (o = !0);
360
372
  }
361
373
  return o;
362
374
  }
363
- async function xe(e, r, t, n) {
375
+ async function Te(e, r, t, n) {
364
376
  const o = n.stack[n.stack.length - 1];
365
377
  if (e.attributes.xpointer)
366
378
  throw new Error(
@@ -374,8 +386,8 @@ async function xe(e, r, t, n) {
374
386
  s = decodeURIComponent(i);
375
387
  } catch {
376
388
  }
377
- const a = u.resolve(r, s);
378
- if (a !== n.projectDir && !a.startsWith(n.projectDir + u.sep))
389
+ const a = f.resolve(r, s);
390
+ if (a !== n.projectDir && !a.startsWith(n.projectDir + f.sep))
379
391
  throw new Error(
380
392
  `xi:include escapes the project directory: ${i} (in ${o})`
381
393
  );
@@ -383,20 +395,20 @@ async function xe(e, r, t, n) {
383
395
  throw new Error(
384
396
  `Circular xi:include: ${[...n.stack, a].join(" -> ")}`
385
397
  );
386
- if (n.stack.length >= ne)
387
- throw new Error(`xi:include nesting exceeds ${ne} levels`);
388
- const l = await M(a);
389
- if (l === void 0) {
390
- const p = mt(e, t);
398
+ if (n.stack.length >= re)
399
+ throw new Error(`xi:include nesting exceeds ${re} levels`);
400
+ const c = await j(a);
401
+ if (c === void 0) {
402
+ const p = vt(e, t);
391
403
  if (p)
392
- return await P(p, r, t, n), p.children;
404
+ return await R(p, r, t, n), p.children;
393
405
  throw new Error(`xi:include target not found: ${i} (in ${o})`);
394
406
  }
395
407
  if (e.attributes.parse === "text")
396
- return [{ type: "text", value: l }];
397
- let c;
408
+ return [{ type: "text", value: c }];
409
+ let l;
398
410
  try {
399
- c = E(l);
411
+ l = E(c);
400
412
  } catch (p) {
401
413
  throw new Error(
402
414
  `Could not parse xi:include target ${a} as XML: ${p instanceof Error ? p.message : p}. (Included files must be well-formed, with a single root element.)`
@@ -404,48 +416,48 @@ async function xe(e, r, t, n) {
404
416
  }
405
417
  n.stack.push(a);
406
418
  try {
407
- await P(c, u.dirname(a), { "": "" }, n);
419
+ await R(l, f.dirname(a), { "": "" }, n);
408
420
  } finally {
409
421
  n.stack.pop();
410
422
  }
411
- const f = c.children.filter(
423
+ const u = l.children.filter(
412
424
  (p) => p.type === "element"
413
425
  );
414
- for (const p of f)
415
- ft(p, a);
416
- return f;
426
+ for (const p of u)
427
+ wt(p, a);
428
+ return u;
417
429
  }
418
- function re(e) {
430
+ function oe(e) {
419
431
  return e.name === "docinfo";
420
432
  }
421
- async function pt(e, r, t) {
433
+ async function bt(e, r, t) {
422
434
  try {
423
435
  const o = E(e).children.find(
424
- (c) => c.type === "element"
436
+ (l) => l.type === "element"
425
437
  );
426
438
  if (!o)
427
439
  return;
428
- const i = u.resolve(r), s = u.dirname(i), a = {
429
- projectDir: u.resolve(t),
440
+ const i = f.resolve(r), s = f.dirname(i), a = {
441
+ projectDir: f.resolve(t),
430
442
  stack: [i]
431
- }, l = L({ "": "" }, o);
432
- for (const c of o.children) {
433
- if (c.type !== "element")
443
+ }, c = L({ "": "" }, o);
444
+ for (const l of o.children) {
445
+ if (l.type !== "element")
434
446
  continue;
435
- const f = L(l, c);
436
- if (re(c))
437
- return await P(c, s, f, a), I(c);
438
- if (ve(c, f)) {
439
- const m = (await xe(
440
- c,
447
+ const u = L(c, l);
448
+ if (oe(l))
449
+ return await R(l, s, u, a), I(l);
450
+ if (ye(l, u)) {
451
+ const h = (await Te(
452
+ l,
441
453
  s,
442
- f,
454
+ u,
443
455
  a
444
456
  )).find(
445
- (h) => h.type === "element" && re(h)
457
+ (m) => m.type === "element" && oe(m)
446
458
  );
447
- if (m)
448
- return I(m);
459
+ if (h)
460
+ return I(h);
449
461
  continue;
450
462
  }
451
463
  break;
@@ -455,67 +467,67 @@ async function pt(e, r, t) {
455
467
  return;
456
468
  }
457
469
  }
458
- function mt(e, r) {
470
+ function vt(e, r) {
459
471
  for (const t of e.children) {
460
472
  if (t.type !== "element")
461
473
  continue;
462
474
  const n = L(r, t), o = t.name.indexOf(":"), i = o === -1 ? "" : t.name.slice(0, o);
463
- if ((o === -1 ? t.name : t.name.slice(o + 1)) === "fallback" && n[i] === ge)
475
+ if ((o === -1 ? t.name : t.name.slice(o + 1)) === "fallback" && n[i] === xe)
464
476
  return t;
465
477
  }
466
478
  }
467
- function ye(e) {
479
+ function Ee(e) {
468
480
  return typeof e == "object" && e !== null && e.type === "element";
469
481
  }
470
- function ht(e) {
482
+ function gt(e) {
471
483
  return /^(pf|xhtml):/.test(e.name);
472
484
  }
473
- function wt(e, r, t) {
474
- const n = [], o = e.children.find(ye);
485
+ function xt(e, r, t) {
486
+ const n = [], o = e.children.find(Ee);
475
487
  if (o) {
476
488
  const i = t?.parentId ?? "root";
477
- Te(o, i, t?.position ?? 1, r, i, n);
489
+ Se(o, i, t?.position ?? 1, r, i, n);
478
490
  }
479
491
  return n;
480
492
  }
481
- function Te(e, r, t, n, o, i) {
482
- const s = dt(e) ?? n;
483
- let a, l;
484
- if (ht(e))
485
- l = "root";
493
+ function Se(e, r, t, n, o, i) {
494
+ const s = mt(e) ?? n;
495
+ let a, c;
496
+ if (gt(e))
497
+ c = "root";
486
498
  else {
487
- const f = e.attributes.label ?? e.attributes["xml:id"];
488
- a = f ?? `${r}-${t}`, i.push({
499
+ const u = e.attributes.label ?? e.attributes["xml:id"];
500
+ a = u ?? `${r}-${t}`, i.push({
489
501
  id: a,
490
502
  file: s,
491
503
  line: e.position?.start.line ?? 1,
492
504
  column: e.position?.start.column ?? 1,
493
505
  endLine: e.position?.end.line ?? e.position?.start.line ?? 1,
494
506
  parent: o
495
- }), l = a;
507
+ }), c = a;
496
508
  }
497
- let c = 0;
498
- for (const f of e.children)
499
- ye(f) && (c += 1, Te(
500
- f,
501
- l,
509
+ let l = 0;
510
+ for (const u of e.children)
511
+ Ee(u) && (l += 1, Se(
512
+ u,
502
513
  c,
514
+ l,
503
515
  s,
504
516
  a ?? o,
505
517
  i
506
518
  ));
507
519
  }
508
- function nn(e, r) {
520
+ function cn(e, r) {
509
521
  let t;
510
522
  for (const n of e)
511
523
  n.line <= r && (t = n);
512
524
  return t ?? e[0];
513
525
  }
514
- function bt(e) {
526
+ function yt(e) {
515
527
  const r = e.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, " ");
516
528
  return /<\s*slide(?:show)?[\s/>]/.test(r) ? "slides" : "html";
517
529
  }
518
- const Ee = /* @__PURE__ */ new Set([
530
+ const ke = /* @__PURE__ */ new Set([
519
531
  "colophon",
520
532
  "biography",
521
533
  "dedication",
@@ -535,19 +547,19 @@ const Ee = /* @__PURE__ */ new Set([
535
547
  "glossary",
536
548
  "worksheet",
537
549
  "handout"
538
- ]), Se = /* @__PURE__ */ new Set([
550
+ ]), $e = /* @__PURE__ */ new Set([
539
551
  "book",
540
552
  "article",
541
553
  "slideshow",
542
554
  "letter",
543
555
  "memo"
544
- ]), ke = /* @__PURE__ */ new Set([
545
- ...Se,
546
- ...Ee,
556
+ ]), Pe = /* @__PURE__ */ new Set([
557
+ ...$e,
558
+ ...ke,
547
559
  "part",
548
560
  "frontmatter",
549
561
  "backmatter"
550
- ]), gt = /* @__PURE__ */ new Set(["docinfo"]), $e = /* @__PURE__ */ new Set([
562
+ ]), Tt = /* @__PURE__ */ new Set(["docinfo"]), Ie = /* @__PURE__ */ new Set([
551
563
  "title",
552
564
  "shorttitle",
553
565
  "plaintitle",
@@ -557,13 +569,13 @@ const Ee = /* @__PURE__ */ new Set([
557
569
  function g(e) {
558
570
  return e.type === "element";
559
571
  }
560
- function Ie(e) {
572
+ function Re(e) {
561
573
  return e.attributes["xml:id"] ?? void 0;
562
574
  }
563
575
  function X(e, r) {
564
576
  for (const t of e.children) {
565
577
  if (!g(t)) continue;
566
- if (Ie(t) === r) return t;
578
+ if (Re(t) === r) return t;
567
579
  const n = X(t, r);
568
580
  if (n) return n;
569
581
  }
@@ -576,28 +588,28 @@ function A(e, r) {
576
588
  if (n) return [t, ...n];
577
589
  }
578
590
  }
579
- function vt(e, r) {
591
+ function Et(e, r) {
580
592
  let t = 0;
581
593
  for (const [n, o] of e.entries()) {
582
594
  const i = n === 0 ? void 0 : e[n - 1];
583
- Se.has(o.name) ? t = 0 : o.name === "frontmatter" || o.name === "backmatter" || o.name === "part" ? t = i?.name === "book" && r ? 1 : 0 : Ee.has(o.name) && (t += 1);
595
+ $e.has(o.name) ? t = 0 : o.name === "frontmatter" || o.name === "backmatter" || o.name === "part" ? t = i?.name === "book" && r ? 1 : 0 : ke.has(o.name) && (t += 1);
584
596
  }
585
597
  return t;
586
598
  }
587
- function Pe(e) {
588
- if (!$e.has(e.name)) {
599
+ function De(e) {
600
+ if (!Ie.has(e.name)) {
589
601
  e.children = e.children.filter(g);
590
602
  for (const r of e.children)
591
- Pe(r);
603
+ De(r);
592
604
  }
593
605
  }
594
606
  function U(e, r) {
595
607
  const t = [];
596
608
  for (const n of e.children)
597
- g(n) && (r.has(n) || gt.has(n.name) || $e.has(n.name) ? t.push(n) : ke.has(n.name) && (U(n, r), t.push(n)));
609
+ g(n) && (r.has(n) || Tt.has(n.name) || Ie.has(n.name) ? t.push(n) : Pe.has(n.name) && (U(n, r), t.push(n)));
598
610
  e.children = t;
599
611
  }
600
- function xt(e) {
612
+ function St(e) {
601
613
  const r = /* @__PURE__ */ new Set(), t = (n) => {
602
614
  if (n.name === "xref") {
603
615
  const o = [
@@ -614,11 +626,11 @@ function xt(e) {
614
626
  };
615
627
  return t(e), r;
616
628
  }
617
- function yt(e, r, t) {
629
+ function kt(e, r, t) {
618
630
  const n = (o) => {
619
631
  for (const [i, s] of o.children.entries())
620
632
  if (g(s)) {
621
- if (Ie(s) === r)
633
+ if (Re(s) === r)
622
634
  return o.children[i] = t, !0;
623
635
  if (n(s)) return !0;
624
636
  }
@@ -626,49 +638,49 @@ function yt(e, r, t) {
626
638
  };
627
639
  return n(e);
628
640
  }
629
- function Tt(e, r) {
641
+ function $t(e, r) {
630
642
  const t = X(e, r);
631
643
  if (!t) return;
632
644
  const n = A(e, t);
633
645
  if (!n) return;
634
646
  const o = n.filter(
635
- (m) => m.name !== "pretext" && m.name !== "mathbook"
647
+ (h) => h.name !== "pretext" && h.name !== "mathbook"
636
648
  ), i = o[0], s = i?.name === "book" && i.children.some(
637
- (m) => g(m) && m.name === "part"
638
- ), a = vt(o, s), l = new Set(n), c = xt(t), f = /* @__PURE__ */ new Set();
639
- if (c.size > 0)
640
- for (const m of c) {
641
- const h = X(e, m);
642
- if (!h || h === t) continue;
643
- const R = A(e, h);
644
- if (!R) continue;
645
- const v = [...R].reverse().find((b) => ke.has(b.name));
646
- if (v && v !== t) {
647
- f.add(v);
648
- for (const b of A(e, v) ?? [])
649
- l.add(b);
649
+ (h) => g(h) && h.name === "part"
650
+ ), a = Et(o, s), c = new Set(n), l = St(t), u = /* @__PURE__ */ new Set();
651
+ if (l.size > 0)
652
+ for (const h of l) {
653
+ const m = X(e, h);
654
+ if (!m || m === t) continue;
655
+ const D = A(e, m);
656
+ if (!D) continue;
657
+ const x = [...D].reverse().find((v) => Pe.has(v.name));
658
+ if (x && x !== t) {
659
+ u.add(x);
660
+ for (const v of A(e, x) ?? [])
661
+ c.add(v);
650
662
  }
651
663
  }
652
- for (const m of n) {
653
- if (m === t) break;
654
- U(m, l);
664
+ for (const h of n) {
665
+ if (h === t) break;
666
+ U(h, c);
655
667
  }
656
- for (const m of f)
657
- Pe(m);
668
+ for (const h of u)
669
+ De(h);
658
670
  const p = e.children.find(g);
659
- return p && !n.includes(p) && U(p, l), { content: I(e), divisionId: r, level: a };
671
+ return p && !n.includes(p) && U(p, c), { content: I(e), divisionId: r, level: a };
660
672
  }
661
- const Et = "This live preview shows a single division, so links into the rest of the document do not work here.", St = /<a\b([^>]*)>/g, kt = /\sid="([^"]*)"/g, j = /\shref="([^"]*)"/, $t = /\\href\{([^{}]*)\}/g, oe = /\stitle="([^"]*)"/;
662
- function It(e) {
673
+ const Pt = "This live preview shows a single division, so links into the rest of the document do not work here.", It = /<a\b([^>]*)>/g, Rt = /\sid="([^"]*)"/g, _ = /\shref="([^"]*)"/, Dt = /\\href\{([^{}]*)\}/g, ie = /\stitle="([^"]*)"/;
674
+ function At(e) {
663
675
  const r = /* @__PURE__ */ new Set();
664
- for (const t of e.matchAll(kt))
676
+ for (const t of e.matchAll(Rt))
665
677
  r.add(t[1]);
666
678
  return r;
667
679
  }
668
- function Pt(e) {
680
+ function Lt(e) {
669
681
  return e.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
670
682
  }
671
- function ie(e, r) {
683
+ function se(e, r) {
672
684
  if (e.startsWith("#") || e === "") return { kind: "keep" };
673
685
  if (/^[a-z][a-z0-9+.-]*:/i.test(e) || e.startsWith("//"))
674
686
  return { kind: "keep" };
@@ -677,73 +689,73 @@ function ie(e, r) {
677
689
  const n = e.slice(t + 1);
678
690
  return r.has(n) && n !== "" ? { kind: "same-page", id: n } : { kind: "off-page" };
679
691
  }
680
- function Rt(e, r = {}) {
681
- const t = r.offPageMessage ?? Et, n = It(e);
682
- return e.replace(St, (i, s) => {
683
- const a = j.exec(s);
692
+ function jt(e, r = {}) {
693
+ const t = r.offPageMessage ?? Pt, n = At(e);
694
+ return e.replace(It, (i, s) => {
695
+ const a = _.exec(s);
684
696
  if (!a) return i;
685
- const l = ie(a[1], n);
686
- if (l.kind === "keep") return i;
687
- if (l.kind === "same-page")
688
- return `<a${s.replace(j, ` href="#${l.id}"`)}>`;
689
- const c = oe.exec(s), f = Pt(t), p = c ? `${c[1]} — ${f}` : f;
690
- return `<a${s.replace(j, "").replace(oe, "")} title="${p}" aria-disabled="true" style="cursor:default">`;
691
- }).replace($t, (i, s) => {
692
- const a = ie(s, n);
697
+ const c = se(a[1], n);
698
+ if (c.kind === "keep") return i;
699
+ if (c.kind === "same-page")
700
+ return `<a${s.replace(_, ` href="#${c.id}"`)}>`;
701
+ const l = ie.exec(s), u = Lt(t), p = l ? `${l[1]} — ${u}` : u;
702
+ return `<a${s.replace(_, "").replace(ie, "")} title="${p}" aria-disabled="true" style="cursor:default">`;
703
+ }).replace(Dt, (i, s) => {
704
+ const a = se(s, n);
693
705
  return a.kind === "same-page" ? `\\href{#${a.id}}` : i;
694
706
  });
695
707
  }
696
- function Dt() {
697
- return We(C(), "xsl");
708
+ function Mt() {
709
+ return Ke(C(), "xsl");
698
710
  }
699
- function At() {
711
+ function _t() {
700
712
  return "Suspending" in WebAssembly;
701
713
  }
702
- function Lt() {
703
- if (!At())
714
+ function Bt() {
715
+ if (!_t())
704
716
  throw new Error(
705
717
  "WebAssembly JSPI is not enabled. Run Node with --experimental-wasm-jspi (or use the pretext-html CLI, which re-launches itself with the flag)."
706
718
  );
707
719
  }
708
- function $(e) {
720
+ function P(e) {
709
721
  return e.includes("'") ? e.includes('"') ? `concat(${e.split("'").map((t) => `'${t}'`).join(`, "'", `)})` : `"${e}"` : `'${e}'`;
710
722
  }
711
- function Mt(e) {
723
+ function Ot(e) {
712
724
  return e.replace(
713
725
  /from '\.\/(https:\/\/[^']+)'/g,
714
726
  (r, t) => `from '${t}'`
715
727
  );
716
728
  }
717
- const _t = `https://cdn.jsdelivr.net/gh/PreTeXtBook/html-static@${pe}/dist/`, jt = {
718
- "cli.version": pe,
729
+ const Ct = `https://cdn.jsdelivr.net/gh/PreTeXtBook/html-static@${me}/dist/`, Ft = {
730
+ "cli.version": me,
719
731
  // Colon-delimited: pretext-runestone.xsl splits them with str:tokenize.
720
- "rs-js": Je.join(":"),
721
- "rs-css": ze.join(":"),
722
- "rs-version": He
732
+ "rs-js": Ge.join(":"),
733
+ "rs-css": Ye.join(":"),
734
+ "rs-version": Ve
723
735
  };
724
- function Bt(e) {
736
+ function Nt(e) {
725
737
  return e.replace(
726
738
  /(<link\b[^>]*\bhref=["'])_static\//gi,
727
- `$1${_t}_static/`
739
+ `$1${Ct}_static/`
728
740
  );
729
741
  }
730
- function Ot(e) {
742
+ function Xt(e) {
731
743
  return e.slice(0, 65536).replace(/<\?[\s\S]*?\?>/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<!DOCTYPE[^>]*>/gi, " ").match(/<\s*([A-Za-z][\w:-]*)/)?.[1];
732
744
  }
733
- async function se(e) {
734
- const r = await M(e);
745
+ async function ae(e) {
746
+ const r = await j(e);
735
747
  if (r === void 0)
736
748
  throw new Error(
737
749
  `Could not read ${e}. (In the browser build only absolute URLs are readable — pass sourceContent instead of relying on sourcePath.)`
738
750
  );
739
751
  return r;
740
752
  }
741
- async function Ct(e, r) {
742
- const t = u.resolve(e), n = await M(t);
753
+ async function Ut(e, r) {
754
+ const t = f.resolve(e), n = await j(t);
743
755
  if (n !== void 0)
744
- return pt(n, t, r);
756
+ return bt(n, t, r);
745
757
  }
746
- function Ft(e, r, t, n) {
758
+ function Wt(e, r, t, n) {
747
759
  const o = e.replace(/^\uFEFF/, "").replace(/<\?xml[\s\S]*?\?>/, "").replace(/<!DOCTYPE[^>]*>/i, ""), i = t === "slides" ? "slideshow" : r === "chapter" || r === "part" ? "book" : "article";
748
760
  return `<pretext>
749
761
  ${n?.trim() ? `${n.trim()}
@@ -754,51 +766,51 @@ ${o}
754
766
  </pretext>
755
767
  `;
756
768
  }
757
- async function Nt(e, r, t, n) {
769
+ async function Ht(e, r, t, n) {
758
770
  const o = E(e).children.find(
759
- (f) => f.type === "element"
771
+ (u) => u.type === "element"
760
772
  ), i = o?.attributes["xml:id"];
761
773
  if (!o || !i) return;
762
- const s = u.resolve(r), a = n ?? await M(s);
774
+ const s = f.resolve(r), a = n ?? await j(s);
763
775
  if (a === void 0) return;
764
- let l;
776
+ let c;
765
777
  try {
766
- l = (await J(a, s, t)).tree;
778
+ c = (await J(a, s, t)).tree;
767
779
  } catch {
768
780
  return;
769
781
  }
770
- if (!yt(l, i, o)) return;
771
- const c = Tt(l, i);
772
- if (c)
773
- return { ...c, tree: l };
782
+ if (!kt(c, i, o)) return;
783
+ const l = $t(c, i);
784
+ if (l)
785
+ return { ...l, tree: c };
774
786
  }
775
- let Re = !1;
776
- function Xt(e) {
787
+ let Ae = !1;
788
+ function Jt(e) {
777
789
  return e instanceof Error && /\bAborted\(/.test(e.message);
778
790
  }
779
- function Ut(e) {
791
+ function zt(e) {
780
792
  return e instanceof Error && /memory access|out of bounds/i.test(e.message);
781
793
  }
782
- function Wt() {
783
- if (Re)
794
+ function Kt() {
795
+ if (Ae)
784
796
  throw new Error(
785
797
  "The WebAssembly renderer aborted earlier in this process and cannot be reused. Restart the process (or reload the page) to render again."
786
798
  );
787
799
  }
788
- function ae(e) {
789
- if (Xt(e))
790
- throw Re = !0, new Error(
800
+ function ce(e) {
801
+ if (Jt(e))
802
+ throw Ae = !0, new Error(
791
803
  "The WebAssembly renderer aborted and cannot be reused. Restart the process (or reload the page) to render again.",
792
804
  { cause: e }
793
805
  );
794
- if (Ut(e))
806
+ if (zt(e))
795
807
  throw new Error(
796
808
  "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.",
797
809
  { cause: e }
798
810
  );
799
811
  }
800
812
  let B;
801
- async function De() {
813
+ async function Le() {
802
814
  return B || (B = (async () => {
803
815
  const [e, r] = await Promise.all([
804
816
  import("@pretextbook/libxslt-wasm"),
@@ -807,121 +819,121 @@ async function De() {
807
819
  return r.registerAll(), e;
808
820
  })()), B;
809
821
  }
810
- const O = /* @__PURE__ */ new Map(), Ht = {
822
+ const O = /* @__PURE__ */ new Map(), Vt = {
811
823
  html: "preview-html.xsl",
812
824
  slides: "preview-revealjs.xsl"
813
825
  };
814
- async function Jt(e, r) {
815
- const t = Ht[r], n = `${r}\0${e}`;
826
+ async function Gt(e, r) {
827
+ const t = Vt[r], n = `${r}\0${e}`;
816
828
  let o = O.get(n);
817
829
  return o || (o = (async () => {
818
- const { XmlDocument: i, XsltStylesheet: s } = await De(), a = be(e), l = await de(C(), `/${t}`);
819
- if (l === void 0)
830
+ const { XmlDocument: i, XsltStylesheet: s } = await Le(), a = ge(e), c = await pe(C(), `/${t}`);
831
+ if (c === void 0)
820
832
  throw new Error(
821
833
  `Could not read ${t} from ${C()}. Check the assets location (PRETEXT_HTML_ASSETS under Node, setAssetsBase() in the browser).`
822
834
  );
823
- const c = new TextDecoder().decode(l), f = await i.fromString(c, {
835
+ const l = new TextDecoder().decode(c), u = await i.fromString(l, {
824
836
  url: `${a}/${t}`,
825
837
  options: { noEnt: !0, dtdLoad: !0, huge: !0 }
826
838
  });
827
- return s.fromXmlDocument(f);
839
+ return s.fromXmlDocument(u);
828
840
  })(), O.set(n, o), o.catch(() => O.delete(n))), o;
829
841
  }
830
- let ce = Promise.resolve();
831
- function zt(e) {
832
- const r = ce.then(
833
- () => le(e),
834
- () => le(e)
842
+ let le = Promise.resolve();
843
+ function Yt(e) {
844
+ const r = le.then(
845
+ () => ue(e),
846
+ () => ue(e)
835
847
  );
836
- return ce = r.catch(() => {
848
+ return le = r.catch(() => {
837
849
  }), r;
838
850
  }
839
- async function le(e) {
840
- Lt(), Wt();
841
- const { XmlDocument: r } = await De(), t = u.resolve(e.sourcePath), n = u.resolve(
842
- e.projectDir ?? u.dirname(t)
843
- ), o = e.sourceContent ?? await se(t), i = u.relative(n, t);
851
+ async function ue(e) {
852
+ Bt(), Kt();
853
+ const { XmlDocument: r } = await Le(), t = f.resolve(e.sourcePath), n = f.resolve(
854
+ e.projectDir ?? f.dirname(t)
855
+ ), o = e.sourceContent ?? await ae(t), i = f.relative(n, t);
844
856
  if (i.startsWith(".."))
845
857
  throw new Error(
846
858
  `sourcePath (${t}) must live inside projectDir (${n})`
847
859
  );
848
- const s = u.relative(
860
+ const s = f.relative(
849
861
  n,
850
- u.resolve(e.mainSourcePath ?? t)
851
- ), a = s.startsWith("..") ? i : s, l = be(n);
862
+ f.resolve(e.mainSourcePath ?? t)
863
+ ), a = s.startsWith("..") ? i : s, c = ge(n);
852
864
  try {
853
- let c, f = `${l}/__pretext-preview-publication.xml`;
865
+ let l, u = `${c}/__pretext-preview-publication.xml`;
854
866
  if (e.publicationPath) {
855
- const d = u.resolve(e.publicationPath);
856
- c = await se(d);
857
- const w = u.relative(n, d);
858
- w.startsWith("..") || (f = `${l}/${w.split(u.sep).join("/")}`);
867
+ const d = f.resolve(e.publicationPath);
868
+ l = await ae(d);
869
+ const w = f.relative(n, d);
870
+ w.startsWith("..") || (u = `${c}/${w.split(f.sep).join("/")}`);
859
871
  }
860
- let p, m;
872
+ let p, h;
861
873
  if (e.sourceMap) {
862
874
  const d = await J(
863
875
  o,
864
876
  t,
865
877
  n
866
878
  );
867
- p = d.tree, m = d.content;
879
+ p = d.tree, h = d.content;
868
880
  } else
869
- m = await ut(
881
+ h = await ht(
870
882
  o,
871
883
  t,
872
884
  n
873
885
  );
874
- const h = e.target ?? bt(m), R = await Jt(e.xslDir ?? Dt(), h), v = ct(c, {
886
+ const m = e.target ?? yt(h), D = await Gt(e.xslDir ?? Mt(), m), x = ft(l, {
875
887
  cssTheme: e.cssTheme,
876
888
  revealTheme: e.revealTheme,
877
- target: h
889
+ target: m
878
890
  });
879
- rt(f, v);
880
- const b = lt(v), z = u.dirname(u.resolve(n, a)), K = b.external !== void 0 && b.generated !== void 0 ? {
881
- external: u.resolve(z, b.external),
882
- generated: u.resolve(z, b.generated)
883
- } : void 0, D = Ot(m);
884
- let V = { parentId: "root", position: 1 }, S, G = t;
885
- if (D !== "pretext" && D !== "mathbook") {
891
+ at(u, x);
892
+ const v = pt(x), z = f.dirname(f.resolve(n, a)), K = v.external !== void 0 && v.generated !== void 0 ? {
893
+ external: f.resolve(z, v.external),
894
+ generated: f.resolve(z, v.generated)
895
+ } : void 0, S = Xt(h);
896
+ let V = { parentId: "root", position: 1 }, k, G = t;
897
+ if (S !== "pretext" && S !== "mathbook") {
886
898
  if (!e.fragment)
887
899
  throw new Error(
888
- `The document root is <${D ?? "?"}>, not <pretext> — this looks like an xi:included fragment. Render the project's main source file instead, or pass the fragment option.`
900
+ `The document root is <${S ?? "?"}>, not <pretext> — this looks like an xi:included fragment. Render the project's main source file instead, or pass the fragment option.`
889
901
  );
890
902
  if (e.contextSourcePath || e.contextSourceContent) {
891
- const d = e.contextSourcePath ?? u.join(u.dirname(t), "__pretext-preview-context.ptx"), w = await Nt(
892
- m,
903
+ const d = e.contextSourcePath ?? f.join(f.dirname(t), "__pretext-preview-context.ptx"), w = await Ht(
904
+ h,
893
905
  d,
894
906
  n,
895
907
  e.contextSourceContent
896
908
  );
897
- w && (m = w.content, p = e.sourceMap ? w.tree : void 0, G = u.resolve(d), S = { divisionId: w.divisionId, level: w.level });
909
+ w && (h = w.content, p = e.sourceMap ? w.tree : void 0, G = f.resolve(d), k = { divisionId: w.divisionId, level: w.level });
898
910
  }
899
- if (!S) {
900
- const d = e.docinfo ?? (e.docinfoSourcePath ? await Ct(e.docinfoSourcePath, n) : void 0);
901
- m = Ft(
902
- m,
903
- D,
911
+ if (!k) {
912
+ const d = e.docinfo ?? (e.docinfoSourcePath ? await Ut(e.docinfoSourcePath, n) : void 0);
913
+ h = Wt(
904
914
  h,
915
+ S,
916
+ m,
905
917
  d
906
918
  ), V = { parentId: d?.trim() ? "root-1-2" : "root-1-1", position: 2 };
907
919
  }
908
920
  }
909
- const Y = p ? wt(p, G, V) : void 0, q = await r.fromString(m, {
910
- url: `${l}/${a.split(u.sep).join("/")}`,
921
+ const Y = p ? xt(p, G, V) : void 0, q = await r.fromString(h, {
922
+ url: `${c}/${a.split(f.sep).join("/")}`,
911
923
  options: { noEnt: !0, dtdLoad: !0, huge: !0 }
912
- }), k = {
913
- publisher: $(f)
924
+ }), $ = {
925
+ publisher: P(u)
914
926
  };
915
- for (const [d, w] of Object.entries(jt))
916
- k[d] = $(w);
917
- S && (k.subtree = $(S.divisionId), k["subtree-level"] = $(String(S.level)));
927
+ for (const [d, w] of Object.entries(Ft))
928
+ $[d] = P(w);
929
+ k && ($.subtree = P(k.divisionId), $["subtree-level"] = P(String(k.level)));
918
930
  for (const [d, w] of Object.entries(e.stringParams ?? {}))
919
- k[d] = $(w);
920
- let _;
931
+ $[d] = P(w);
932
+ let M;
921
933
  try {
922
- _ = await R.apply(q, k);
934
+ M = await D.apply(q, $);
923
935
  } catch (d) {
924
- throw ae(d), new Error(
936
+ throw ce(d), new Error(
925
937
  "PreTeXt XSLT transform failed; see the PTX:ERROR/PTX:FATAL messages on stderr for details.",
926
938
  { cause: d }
927
939
  );
@@ -929,27 +941,31 @@ async function le(e) {
929
941
  q.delete();
930
942
  }
931
943
  try {
932
- let d = Mt(_.toHtmlString());
933
- return d = Rt(d, {
944
+ let d = Ot(M.toHtmlString());
945
+ d = jt(d, {
934
946
  ...e.offPageMessage !== void 0 ? { offPageMessage: e.offPageMessage } : {}
935
- }), (e.openKnowls ?? !0) && (d = qe(d)), h === "slides" ? (d = Bt(d), d = Le(d, e.revealView ?? "scroll", {
947
+ }), (e.openKnowls ?? !0) && (d = tt(d)), m === "slides" ? (d = Nt(d), d = Be(d, e.revealView ?? "scroll", {
936
948
  zoom: e.revealZoom
937
- })) : e.theme && (d = Me(d, e.theme)), e.previewBanner && (d = Ue(d, e.previewBanner)), {
949
+ })) : e.theme && (d = Oe(d, e.theme)), e.previewBanner && (d = ze(d, e.previewBanner));
950
+ const w = m === "slides" ? [] : je(d), Z = Me(w, S);
951
+ return e.printPreview && (d = fe(d, e.printPreview)), {
938
952
  html: d,
939
- target: h,
953
+ target: m,
954
+ printouts: w,
940
955
  ...Y ? { sourceMap: Y } : {},
941
- ...K ? { assetDirs: K } : {}
956
+ ...K ? { assetDirs: K } : {},
957
+ ...Z ? { rootPrintout: Z } : {}
942
958
  };
943
959
  } catch (d) {
944
- throw ae(d), d;
960
+ throw ce(d), d;
945
961
  } finally {
946
- _.delete();
962
+ M.delete();
947
963
  }
948
964
  } finally {
949
- nt(l);
965
+ st(c);
950
966
  }
951
967
  }
952
- const ue = `Usage: pretext-html <source.ptx> [options]
968
+ const de = `Usage: pretext-html <source.ptx> [options]
953
969
 
954
970
  Render a PreTeXt document to a single standalone HTML page (portable build:
955
971
  one page, css/js/MathJax from CDN). No PreTeXt installation required.
@@ -987,67 +1003,82 @@ Options:
987
1003
  knowls collapsed, as a real PreTeXt build does.
988
1004
  They are expanded by default, since these pages
989
1005
  are previews of work in progress
1006
+ --print-preview[=id] Open the page in the print-preview layout: the
1007
+ named printout paginated to a paper size, with
1008
+ workspaces at their true height. Without an id, the
1009
+ document's own printout is used (a lone worksheet
1010
+ or handout), or failing that its first. The page's
1011
+ printouts are listed on stderr
990
1012
  -h, --help Show this help
991
1013
  `;
992
- function Kt(e) {
993
- let r, t, n, o;
994
- const i = {}, s = {};
995
- for (let a = 0; a < e.length; a++) {
996
- const l = e[a], c = () => {
997
- if (a += 1, a >= e.length)
1014
+ function qt(e) {
1015
+ let r, t, n, o, i;
1016
+ const s = {}, a = {};
1017
+ for (let c = 0; c < e.length; c++) {
1018
+ const l = e[c], u = () => {
1019
+ if (c += 1, c >= e.length)
998
1020
  throw new Error(`Missing value for ${l}`);
999
- return e[a];
1021
+ return e[c];
1000
1022
  };
1001
1023
  switch (l) {
1002
1024
  case "-h":
1003
1025
  case "--help":
1004
- y.stdout.write(ue), y.exit(0);
1026
+ b.stdout.write(de), b.exit(0);
1005
1027
  break;
1006
1028
  case "-o":
1007
1029
  case "--output":
1008
- t = c();
1030
+ t = u();
1009
1031
  break;
1010
1032
  case "--publication":
1011
- i.publicationPath = c();
1033
+ s.publicationPath = u();
1012
1034
  break;
1013
1035
  case "--css-theme":
1014
- i.cssTheme = c();
1036
+ s.cssTheme = u();
1015
1037
  break;
1016
1038
  case "--project-dir":
1017
- i.projectDir = c();
1039
+ s.projectDir = u();
1018
1040
  break;
1019
1041
  case "--xsl-dir":
1020
- i.xslDir = c();
1042
+ s.xslDir = u();
1021
1043
  break;
1022
1044
  case "--fragment":
1023
- i.fragment = !0;
1045
+ s.fragment = !0;
1024
1046
  break;
1025
1047
  case "--no-open-knowls":
1026
- i.openKnowls = !1;
1048
+ s.openKnowls = !1;
1027
1049
  break;
1028
1050
  case "--docinfo":
1029
- n = c();
1051
+ n = u();
1030
1052
  break;
1031
1053
  case "--docinfo-source":
1032
- i.docinfoSourcePath = c();
1054
+ s.docinfoSourcePath = u();
1033
1055
  break;
1034
1056
  case "--context":
1035
- i.contextSourcePath = c();
1057
+ s.contextSourcePath = u();
1036
1058
  break;
1037
1059
  case "--off-page-message":
1038
- i.offPageMessage = c();
1060
+ s.offPageMessage = u();
1039
1061
  break;
1040
1062
  case "--source-map":
1041
- o = c(), i.sourceMap = !0;
1063
+ o = u(), s.sourceMap = !0;
1064
+ break;
1065
+ // Attached form only (--print-preview=<id>), so that a bare
1066
+ // --print-preview cannot swallow the source file as its id.
1067
+ case "--print-preview":
1068
+ i = !0;
1042
1069
  break;
1043
1070
  case "--param": {
1044
- const f = c(), p = f.indexOf("=");
1045
- if (p === -1)
1046
- throw new Error(`--param expects name=value, got: ${f}`);
1047
- s[f.slice(0, p)] = f.slice(p + 1);
1071
+ const p = u(), h = p.indexOf("=");
1072
+ if (h === -1)
1073
+ throw new Error(`--param expects name=value, got: ${p}`);
1074
+ a[p.slice(0, h)] = p.slice(h + 1);
1048
1075
  break;
1049
1076
  }
1050
1077
  default:
1078
+ if (l.startsWith("--print-preview=")) {
1079
+ i = l.slice(16);
1080
+ break;
1081
+ }
1051
1082
  if (l.startsWith("-"))
1052
1083
  throw new Error(`Unknown option: ${l}`);
1053
1084
  if (r)
@@ -1058,42 +1089,57 @@ function Kt(e) {
1058
1089
  if (!r)
1059
1090
  throw new Error(`No source file given.
1060
1091
 
1061
- ` + ue);
1062
- return Object.keys(s).length > 0 && (i.stringParams = s), {
1063
- options: { ...i, sourcePath: r },
1092
+ ` + de);
1093
+ return Object.keys(a).length > 0 && (s.stringParams = a), {
1094
+ options: { ...s, sourcePath: r },
1064
1095
  output: t,
1065
1096
  docinfoPath: n,
1066
- sourceMapPath: o
1097
+ sourceMapPath: o,
1098
+ printPreview: i
1067
1099
  };
1068
1100
  }
1069
- async function rn(e) {
1070
- const { options: r, output: t, docinfoPath: n, sourceMapPath: o } = Kt(e);
1101
+ async function ln(e) {
1102
+ const { options: r, output: t, docinfoPath: n, sourceMapPath: o, printPreview: i } = qt(e);
1071
1103
  n && (r.docinfo = await W(n, "utf8"));
1072
- const i = Date.now(), { html: s, sourceMap: a } = await zt(r);
1073
- y.stderr.write(`pretext-html: rendered in ${Date.now() - i}ms
1074
- `), o && a && (await Z(o, JSON.stringify(a, null, 2)), y.stderr.write(`pretext-html: wrote ${o}
1075
- `)), t ? (await Z(t, s), y.stderr.write(`pretext-html: wrote ${t}
1076
- `)) : y.stdout.write(s);
1104
+ const s = Date.now(), a = await Yt(r), { sourceMap: c, printouts: l, rootPrintout: u } = a;
1105
+ let p = a.html;
1106
+ if (b.stderr.write(`pretext-html: rendered in ${Date.now() - s}ms
1107
+ `), i !== void 0) {
1108
+ for (const m of l)
1109
+ b.stderr.write(
1110
+ `pretext-html: printout ${m.id} - ${m.label}
1111
+ `
1112
+ );
1113
+ const h = typeof i == "string" ? i : u ?? l[0]?.id;
1114
+ h ? (b.stderr.write(`pretext-html: print preview of ${h}
1115
+ `), p = fe(p, h)) : b.stderr.write(
1116
+ `pretext-html: --print-preview: this document has no printouts (worksheet, handout, or project with a workspace); writing the ordinary page.
1117
+ `
1118
+ );
1119
+ }
1120
+ o && c && (await Q(o, JSON.stringify(c, null, 2)), b.stderr.write(`pretext-html: wrote ${o}
1121
+ `)), t ? (await Q(t, p), b.stderr.write(`pretext-html: wrote ${t}
1122
+ `)) : b.stdout.write(p);
1077
1123
  }
1078
1124
  export {
1079
- Et as O,
1080
- _e as P,
1081
- bt as a,
1082
- Tt as b,
1083
- vt as c,
1084
- Dt as d,
1085
- ct as e,
1086
- nn as f,
1087
- At as g,
1088
- yt as h,
1089
- Ue as i,
1090
- Rt as j,
1091
- tn as k,
1092
- Kt as l,
1093
- rn as m,
1094
- qe as o,
1095
- Ce as p,
1096
- zt as r,
1097
- en as s,
1098
- $ as x
1125
+ Pt as O,
1126
+ Ce as P,
1127
+ yt as a,
1128
+ $t as b,
1129
+ Et as c,
1130
+ Mt as d,
1131
+ ft as e,
1132
+ cn as f,
1133
+ _t as g,
1134
+ kt as h,
1135
+ ze as i,
1136
+ jt as j,
1137
+ an as k,
1138
+ qt as l,
1139
+ ln as m,
1140
+ tt as o,
1141
+ Ue as p,
1142
+ Yt as r,
1143
+ sn as s,
1144
+ P as x
1099
1145
  };