@pretextbook/pretext-html 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -3
- package/assets/preview-html.xsl +230 -230
- package/assets/upstream.json +7 -7
- package/assets/xsl/README.md +0 -0
- package/assets/xsl/entities.ent +154 -154
- package/assets/xsl/extract-asymptote.xsl +68 -68
- package/assets/xsl/extract-biblio-csl.xsl +327 -327
- package/assets/xsl/extract-datafile.xsl +71 -71
- package/assets/xsl/extract-dynamic.xsl +139 -139
- package/assets/xsl/extract-identity.xsl +136 -136
- package/assets/xsl/extract-interactive.xsl +81 -81
- package/assets/xsl/extract-latex-image.xsl +118 -118
- package/assets/xsl/extract-mermaid.xsl +58 -58
- package/assets/xsl/extract-mom.xsl +63 -63
- package/assets/xsl/extract-pg.xsl +2897 -2897
- package/assets/xsl/extract-prefigure.xsl +157 -157
- package/assets/xsl/extract-qrcode.xsl +100 -100
- package/assets/xsl/extract-runestone-page-template.xsl +139 -139
- package/assets/xsl/extract-sageplot.xsl +166 -166
- package/assets/xsl/extract-stack.xsl +56 -56
- package/assets/xsl/extract-trace.xsl +134 -134
- package/assets/xsl/extract-youtube.xsl +63 -63
- package/assets/xsl/html-symbols.xsl +3344 -3344
- package/assets/xsl/latex/pretext-latex-AIM.xsl +56 -56
- package/assets/xsl/latex/pretext-latex-CLP.xsl +148 -148
- package/assets/xsl/latex/pretext-latex-chaos.xsl +317 -317
- package/assets/xsl/latex/pretext-latex-dyslexic-font.xsl +76 -76
- package/assets/xsl/latex/pretext-latex-guide.xsl +104 -104
- package/assets/xsl/latex/pretext-latex-texstyle.xsl +862 -862
- package/assets/xsl/localizations/README.md +0 -0
- package/assets/xsl/localizations/af-ZA.xml +276 -276
- package/assets/xsl/localizations/bg-BG.xml +276 -276
- package/assets/xsl/localizations/ca-ES.xml +285 -285
- package/assets/xsl/localizations/cs-CZ.xml +280 -280
- package/assets/xsl/localizations/de-DE.xml +281 -281
- package/assets/xsl/localizations/en-US.xml +427 -427
- package/assets/xsl/localizations/es-ES.xml +287 -287
- package/assets/xsl/localizations/fi-FI.xml +275 -275
- package/assets/xsl/localizations/fr-CA.xml +276 -276
- package/assets/xsl/localizations/fr-FR.xml +280 -280
- package/assets/xsl/localizations/hu-HU.xml +280 -280
- package/assets/xsl/localizations/it-IT.xml +276 -276
- package/assets/xsl/localizations/ku-CKB.xml +275 -275
- package/assets/xsl/localizations/localizations.xml +48 -48
- package/assets/xsl/localizations/nl-NL.xml +275 -275
- package/assets/xsl/localizations/pt-BR.xml +288 -288
- package/assets/xsl/localizations/pt-PT.xml +292 -292
- package/assets/xsl/localizations/zh-HANS.xml +269 -269
- package/assets/xsl/pretext-assembly.xsl +4795 -4795
- package/assets/xsl/pretext-basic-html.xsl +86 -86
- package/assets/xsl/pretext-beamer.xsl +662 -662
- package/assets/xsl/pretext-braille-preprint.xsl +2249 -2249
- package/assets/xsl/pretext-common.xsl +12018 -12018
- package/assets/xsl/pretext-dynamic.xsl +65 -65
- package/assets/xsl/pretext-epub.xsl +1483 -1483
- package/assets/xsl/pretext-fo.xsl +4593 -4593
- package/assets/xsl/pretext-html.xsl +14791 -14791
- package/assets/xsl/pretext-json-manifest.xsl +150 -150
- package/assets/xsl/pretext-jupyter.xsl +868 -868
- package/assets/xsl/pretext-latex-classic.xsl +952 -952
- package/assets/xsl/pretext-latex-common.xsl +11563 -11563
- package/assets/xsl/pretext-latex.xsl +47 -47
- package/assets/xsl/pretext-litprog.xsl +105 -105
- package/assets/xsl/pretext-merge.xsl +41 -41
- package/assets/xsl/pretext-numbers.xsl +875 -875
- package/assets/xsl/pretext-revealjs.xsl +522 -522
- package/assets/xsl/pretext-runestone-fitb.xsl +1233 -1233
- package/assets/xsl/pretext-runestone-static.xsl +1438 -1438
- package/assets/xsl/pretext-runestone.xsl +3083 -3083
- package/assets/xsl/pretext-sage-doctest.xsl +289 -289
- package/assets/xsl/pretext-smc.xsl +492 -492
- package/assets/xsl/pretext-solution-manual-latex.xsl +323 -323
- package/assets/xsl/pretext-text-utilities.xsl +1217 -1217
- package/assets/xsl/pretext-text.xsl +392 -392
- package/assets/xsl/pretext-units.xsl +195 -195
- package/assets/xsl/pretext-view-source.xsl +157 -157
- package/assets/xsl/pretext-ww-problem-sets.xsl +391 -391
- package/assets/xsl/publisher-variables.xsl +4756 -4756
- package/assets/xsl/support/README.md +0 -0
- package/assets/xsl/support/extract-math.xsl +256 -256
- package/assets/xsl/support/package-math.xsl +141 -141
- package/assets/xsl/support/play-button/README.md +0 -0
- package/assets/xsl/support/play-button/play-button.png +0 -0
- package/assets/xsl/support/play-button/play-button.svg +3 -3
- package/assets/xsl/support/pretext-pg-macros.xsl +110 -110
- package/assets/xsl/support/webpack_static_imports.xml +14 -14
- package/assets/xsl/tests/README.md +0 -0
- package/assets/xsl/tests/null.xml +3 -3
- package/assets/xsl/tests/pretext-text-utilities-test.xsl +333 -333
- package/assets/xsl/utilities/README.md +0 -0
- package/assets/xsl/utilities/author-report.xsl +107 -107
- package/assets/xsl/utilities/deprecate-autoname.sed +18 -18
- package/assets/xsl/utilities/deprecate-index.sed +33 -33
- package/assets/xsl/utilities/fix-deprecations.xsl +663 -663
- package/assets/xsl/utilities/pretext-enhanced-source.xsl +112 -112
- package/assets/xsl/utilities/report-publisher-variables.xsl +162 -162
- package/assets/xsl/xml-to-json.xsl +326 -326
- package/assets/xsl/xml-to-string.xsl +328 -328
- package/dist/{cli-C6tfAVvi.js → cli-BQizBK0N.js} +74 -72
- package/dist/cli.d.ts +0 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +12 -6
- package/dist/mounts.d.ts +0 -0
- package/dist/publication.d.ts +0 -0
- package/dist/renderer.d.ts +10 -0
- package/dist/sourcemap.d.ts +0 -0
- package/dist/theme.d.ts +68 -0
- package/dist/theme.js +93 -0
- package/dist/xinclude.d.ts +0 -0
- package/package.json +14 -2
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { readFile as m, writeFile as
|
|
1
|
+
import { readFile as m, writeFile as X } from "node:fs/promises";
|
|
2
2
|
import * as w from "node:process";
|
|
3
3
|
import * as c from "node:path";
|
|
4
4
|
import { fileURLToPath as K } from "node:url";
|
|
5
5
|
import { fromXml as $ } from "xast-util-from-xml";
|
|
6
6
|
import { toXml as y } from "xast-util-to-xml";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import { injectThemeBridge as Q } from "./theme.js";
|
|
8
|
+
const T = /* @__PURE__ */ new Map(), W = /* @__PURE__ */ new Map();
|
|
9
|
+
let S, ee = 0;
|
|
10
|
+
function te(e, r) {
|
|
10
11
|
const t = typeof e == "string" ? e : e instanceof URL ? e.href : e.url, n = W.get(t);
|
|
11
12
|
if (n !== void 0)
|
|
12
13
|
return Promise.resolve(new Response(n, { status: 200 }));
|
|
@@ -16,11 +17,11 @@ function ee(e, r) {
|
|
|
16
17
|
} catch {
|
|
17
18
|
o = "";
|
|
18
19
|
}
|
|
19
|
-
const i =
|
|
20
|
-
return i !== void 0 ?
|
|
20
|
+
const i = T.get(o);
|
|
21
|
+
return i !== void 0 ? re(i, t) : S(e, r);
|
|
21
22
|
}
|
|
22
23
|
const F = '<?xml version="1.0"?><pretext-preview-missing-file/>';
|
|
23
|
-
async function
|
|
24
|
+
async function re(e, r) {
|
|
24
25
|
const t = decodeURIComponent(new URL(r).pathname), n = c.resolve(e, "." + c.posix.normalize(t));
|
|
25
26
|
if (n !== e && !n.startsWith(e + c.sep))
|
|
26
27
|
return console.error(
|
|
@@ -33,21 +34,21 @@ async function te(e, r) {
|
|
|
33
34
|
return new Response(F, { status: 200 });
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
|
-
function
|
|
37
|
-
S || (S = globalThis.fetch, globalThis.fetch =
|
|
37
|
+
function B() {
|
|
38
|
+
S || (S = globalThis.fetch, globalThis.fetch = te);
|
|
38
39
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
const r = `mnt${++
|
|
42
|
-
return
|
|
40
|
+
function N(e) {
|
|
41
|
+
B();
|
|
42
|
+
const r = `mnt${++ee}.ptx.invalid`;
|
|
43
|
+
return T.set(r, c.resolve(e)), `http://${r}`;
|
|
43
44
|
}
|
|
44
|
-
function
|
|
45
|
-
|
|
45
|
+
function ne(e) {
|
|
46
|
+
T.delete(new URL(e).host);
|
|
46
47
|
}
|
|
47
|
-
function
|
|
48
|
-
|
|
48
|
+
function oe(e, r) {
|
|
49
|
+
B(), W.set(e, r);
|
|
49
50
|
}
|
|
50
|
-
const
|
|
51
|
+
const ie = `<?xml version="1.0" encoding="UTF-8"?>
|
|
51
52
|
<publication>
|
|
52
53
|
<source>
|
|
53
54
|
<directories external="../assets" generated="../generated-assets" />
|
|
@@ -68,7 +69,7 @@ function M(e, r) {
|
|
|
68
69
|
}
|
|
69
70
|
function L(e) {
|
|
70
71
|
if (!e)
|
|
71
|
-
return
|
|
72
|
+
return ie;
|
|
72
73
|
const r = $(e), t = _(r, "publication");
|
|
73
74
|
if (!t)
|
|
74
75
|
throw new Error(
|
|
@@ -78,7 +79,7 @@ function L(e) {
|
|
|
78
79
|
return o.attributes = { ...o.attributes, portable: "yes" }, y(r);
|
|
79
80
|
}
|
|
80
81
|
const H = "http://www.w3.org/2001/XInclude", R = 64;
|
|
81
|
-
async function
|
|
82
|
+
async function se(e, r, t) {
|
|
82
83
|
return e.includes("include") ? (await J(e, r, t)).content : e;
|
|
83
84
|
}
|
|
84
85
|
async function J(e, r, t) {
|
|
@@ -93,10 +94,10 @@ async function J(e, r, t) {
|
|
|
93
94
|
);
|
|
94
95
|
return { tree: n, content: i ? y(n) : e };
|
|
95
96
|
}
|
|
96
|
-
function
|
|
97
|
+
function ae(e) {
|
|
97
98
|
return e.data?.ptxIncludedFile;
|
|
98
99
|
}
|
|
99
|
-
function
|
|
100
|
+
function ce(e, r) {
|
|
100
101
|
const t = e.data ?? (e.data = {});
|
|
101
102
|
t.ptxIncludedFile = r;
|
|
102
103
|
}
|
|
@@ -158,7 +159,7 @@ async function z(e, r, t, n) {
|
|
|
158
159
|
try {
|
|
159
160
|
f = await m(s, "utf8");
|
|
160
161
|
} catch {
|
|
161
|
-
const u =
|
|
162
|
+
const u = ue(e, t);
|
|
162
163
|
if (u)
|
|
163
164
|
return await x(u, r, t, n), u.children;
|
|
164
165
|
throw new Error(`xi:include target not found: ${i} (in ${o})`);
|
|
@@ -183,13 +184,13 @@ async function z(e, r, t, n) {
|
|
|
183
184
|
(u) => u.type === "element"
|
|
184
185
|
);
|
|
185
186
|
for (const u of d)
|
|
186
|
-
|
|
187
|
+
ce(u, s);
|
|
187
188
|
return d;
|
|
188
189
|
}
|
|
189
190
|
function A(e) {
|
|
190
191
|
return e.name === "docinfo";
|
|
191
192
|
}
|
|
192
|
-
async function
|
|
193
|
+
async function le(e, r, t) {
|
|
193
194
|
try {
|
|
194
195
|
const o = $(e).children.find(
|
|
195
196
|
(a) => a.type === "element"
|
|
@@ -226,7 +227,7 @@ async function ce(e, r, t) {
|
|
|
226
227
|
return;
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
|
-
function
|
|
230
|
+
function ue(e, r) {
|
|
230
231
|
for (const t of e.children) {
|
|
231
232
|
if (t.type !== "element")
|
|
232
233
|
continue;
|
|
@@ -238,10 +239,10 @@ function le(e, r) {
|
|
|
238
239
|
function G(e) {
|
|
239
240
|
return typeof e == "object" && e !== null && e.type === "element";
|
|
240
241
|
}
|
|
241
|
-
function
|
|
242
|
+
function fe(e) {
|
|
242
243
|
return /^(pf|xhtml):/.test(e.name);
|
|
243
244
|
}
|
|
244
|
-
function
|
|
245
|
+
function de(e, r, t) {
|
|
245
246
|
const n = [], o = e.children.find(G);
|
|
246
247
|
if (o) {
|
|
247
248
|
const i = t?.parentId ?? "root";
|
|
@@ -250,9 +251,9 @@ function fe(e, r, t) {
|
|
|
250
251
|
return n;
|
|
251
252
|
}
|
|
252
253
|
function Y(e, r, t, n, o, i) {
|
|
253
|
-
const l =
|
|
254
|
+
const l = ae(e) ?? n;
|
|
254
255
|
let s, f;
|
|
255
|
-
if (
|
|
256
|
+
if (fe(e))
|
|
256
257
|
f = "root";
|
|
257
258
|
else {
|
|
258
259
|
const d = e.attributes.label ?? e.attributes["xml:id"];
|
|
@@ -276,7 +277,7 @@ function Y(e, r, t, n, o, i) {
|
|
|
276
277
|
i
|
|
277
278
|
));
|
|
278
279
|
}
|
|
279
|
-
function
|
|
280
|
+
function De(e, r) {
|
|
280
281
|
let t;
|
|
281
282
|
for (const n of e)
|
|
282
283
|
n.line <= r && (t = n);
|
|
@@ -285,17 +286,17 @@ function Ie(e, r) {
|
|
|
285
286
|
function V() {
|
|
286
287
|
return process.env.PRETEXT_HTML_ASSETS ?? c.resolve(c.dirname(K(import.meta.url)), "..", "assets");
|
|
287
288
|
}
|
|
288
|
-
function
|
|
289
|
+
function pe() {
|
|
289
290
|
return c.join(V(), "xsl");
|
|
290
291
|
}
|
|
291
|
-
function
|
|
292
|
+
function he() {
|
|
292
293
|
return c.join(V(), "preview-html.xsl");
|
|
293
294
|
}
|
|
294
|
-
function
|
|
295
|
+
function me() {
|
|
295
296
|
return "Suspending" in WebAssembly;
|
|
296
297
|
}
|
|
297
|
-
function
|
|
298
|
-
if (!
|
|
298
|
+
function we() {
|
|
299
|
+
if (!me())
|
|
299
300
|
throw new Error(
|
|
300
301
|
"WebAssembly JSPI is not enabled. Run Node with --experimental-wasm-jspi (or use the pretext-html CLI, which re-launches itself with the flag)."
|
|
301
302
|
);
|
|
@@ -303,16 +304,16 @@ function me() {
|
|
|
303
304
|
function U(e) {
|
|
304
305
|
return e.includes("'") ? e.includes('"') ? `concat(${e.split("'").map((t) => `'${t}'`).join(`, "'", `)})` : `"${e}"` : `'${e}'`;
|
|
305
306
|
}
|
|
306
|
-
function
|
|
307
|
+
function ge(e) {
|
|
307
308
|
return e.replace(
|
|
308
309
|
/from '\.\/(https:\/\/[^']+)'/g,
|
|
309
310
|
(r, t) => `from '${t}'`
|
|
310
311
|
);
|
|
311
312
|
}
|
|
312
|
-
function
|
|
313
|
+
function be(e) {
|
|
313
314
|
return e.slice(0, 65536).replace(/<\?[\s\S]*?\?>/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<!DOCTYPE[^>]*>/gi, " ").match(/<\s*([A-Za-z][\w:-]*)/)?.[1];
|
|
314
315
|
}
|
|
315
|
-
async function
|
|
316
|
+
async function xe(e, r) {
|
|
316
317
|
const t = c.resolve(e);
|
|
317
318
|
let n;
|
|
318
319
|
try {
|
|
@@ -320,9 +321,9 @@ async function be(e, r) {
|
|
|
320
321
|
} catch {
|
|
321
322
|
return;
|
|
322
323
|
}
|
|
323
|
-
return
|
|
324
|
+
return le(n, t, r);
|
|
324
325
|
}
|
|
325
|
-
function
|
|
326
|
+
function ye(e, r, t) {
|
|
326
327
|
const n = e.replace(/^\uFEFF/, "").replace(/<\?xml[\s\S]*?\?>/, "").replace(/<!DOCTYPE[^>]*>/i, ""), o = r === "chapter" || r === "part" ? "book" : "article";
|
|
327
328
|
return `<pretext>
|
|
328
329
|
${t?.trim() ? `${t.trim()}
|
|
@@ -351,27 +352,27 @@ async function Z() {
|
|
|
351
352
|
})()), P;
|
|
352
353
|
}
|
|
353
354
|
const k = /* @__PURE__ */ new Map();
|
|
354
|
-
async function
|
|
355
|
+
async function ve(e) {
|
|
355
356
|
const r = c.resolve(e);
|
|
356
357
|
let t = k.get(r);
|
|
357
358
|
return t || (t = (async () => {
|
|
358
|
-
const { XmlDocument: n, XsltStylesheet: o } = await Z(), i =
|
|
359
|
+
const { XmlDocument: n, XsltStylesheet: o } = await Z(), i = N(r), l = await m(he(), "utf8"), s = await n.fromString(l, {
|
|
359
360
|
url: `${i}/preview-html.xsl`,
|
|
360
361
|
options: { noEnt: !0, dtdLoad: !0, huge: !0 }
|
|
361
362
|
});
|
|
362
363
|
return o.fromXmlDocument(s);
|
|
363
364
|
})(), k.set(r, t), t.catch(() => k.delete(r))), t;
|
|
364
365
|
}
|
|
365
|
-
async function
|
|
366
|
-
|
|
367
|
-
const { XmlDocument: r } = await Z(), t = await
|
|
366
|
+
async function $e(e) {
|
|
367
|
+
we();
|
|
368
|
+
const { XmlDocument: r } = await Z(), t = await ve(e.xslDir ?? pe()), n = c.resolve(e.sourcePath), o = c.resolve(
|
|
368
369
|
e.projectDir ?? c.dirname(n)
|
|
369
370
|
), i = e.sourceContent ?? await m(n, "utf8"), l = c.relative(o, n);
|
|
370
371
|
if (l.startsWith(".."))
|
|
371
372
|
throw new Error(
|
|
372
373
|
`sourcePath (${n}) must live inside projectDir (${o})`
|
|
373
374
|
);
|
|
374
|
-
const s =
|
|
375
|
+
const s = N(o);
|
|
375
376
|
try {
|
|
376
377
|
let f, a = `${s}/__pretext-preview-publication.xml`;
|
|
377
378
|
if (e.publicationPath) {
|
|
@@ -383,7 +384,7 @@ async function ve(e) {
|
|
|
383
384
|
b.startsWith("..") || (a = `${s}/${b.split(c.sep).join("/")}`);
|
|
384
385
|
} else
|
|
385
386
|
f = L();
|
|
386
|
-
|
|
387
|
+
oe(a, f);
|
|
387
388
|
let d, u;
|
|
388
389
|
if (e.sourceMap) {
|
|
389
390
|
const p = await J(
|
|
@@ -393,32 +394,32 @@ async function ve(e) {
|
|
|
393
394
|
);
|
|
394
395
|
d = p.tree, u = p.content;
|
|
395
396
|
} else
|
|
396
|
-
u = await
|
|
397
|
+
u = await se(
|
|
397
398
|
i,
|
|
398
399
|
n,
|
|
399
400
|
o
|
|
400
401
|
);
|
|
401
|
-
const h =
|
|
402
|
+
const h = be(u);
|
|
402
403
|
let g = { parentId: "root", position: 1 };
|
|
403
404
|
if (h !== "pretext" && h !== "mathbook")
|
|
404
405
|
if (e.fragment) {
|
|
405
|
-
const p = e.docinfo ?? (e.docinfoSourcePath ? await
|
|
406
|
-
u =
|
|
406
|
+
const p = e.docinfo ?? (e.docinfoSourcePath ? await xe(e.docinfoSourcePath, o) : void 0);
|
|
407
|
+
u = ye(u, h, p), g = { parentId: p?.trim() ? "root-1-2" : "root-1-1", position: 2 };
|
|
407
408
|
} else
|
|
408
409
|
throw new Error(
|
|
409
410
|
`The document root is <${h ?? "?"}>, not <pretext> — this looks like an xi:included fragment. Render the project's main source file instead, or pass the fragment option.`
|
|
410
411
|
);
|
|
411
|
-
const
|
|
412
|
+
const I = d ? de(d, n, g) : void 0, D = await r.fromString(u, {
|
|
412
413
|
url: `${s}/${l.split(c.sep).join("/")}`,
|
|
413
414
|
options: { noEnt: !0, dtdLoad: !0, huge: !0 }
|
|
414
|
-
}),
|
|
415
|
+
}), j = {
|
|
415
416
|
publisher: U(a)
|
|
416
417
|
};
|
|
417
418
|
for (const [p, b] of Object.entries(e.stringParams ?? {}))
|
|
418
|
-
|
|
419
|
+
j[p] = U(b);
|
|
419
420
|
let E;
|
|
420
421
|
try {
|
|
421
|
-
E = await t.apply(D,
|
|
422
|
+
E = await t.apply(D, j);
|
|
422
423
|
} catch (p) {
|
|
423
424
|
throw C(p), new Error(
|
|
424
425
|
"PreTeXt XSLT transform failed; see the PTX:ERROR/PTX:FATAL messages on stderr for details.",
|
|
@@ -428,9 +429,10 @@ async function ve(e) {
|
|
|
428
429
|
D.delete();
|
|
429
430
|
}
|
|
430
431
|
try {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
432
|
+
let p = ge(E.toHtmlString());
|
|
433
|
+
return e.theme && (p = Q(p, e.theme)), {
|
|
434
|
+
html: p,
|
|
435
|
+
...I ? { sourceMap: I } : {}
|
|
434
436
|
};
|
|
435
437
|
} catch (p) {
|
|
436
438
|
throw C(p), p;
|
|
@@ -438,7 +440,7 @@ async function ve(e) {
|
|
|
438
440
|
E.delete();
|
|
439
441
|
}
|
|
440
442
|
} finally {
|
|
441
|
-
|
|
443
|
+
ne(s);
|
|
442
444
|
}
|
|
443
445
|
}
|
|
444
446
|
const O = `Usage: pretext-html <source.ptx> [options]
|
|
@@ -467,7 +469,7 @@ Options:
|
|
|
467
469
|
file/line for every element (for editor sync)
|
|
468
470
|
-h, --help Show this help
|
|
469
471
|
`;
|
|
470
|
-
function
|
|
472
|
+
function Ee(e) {
|
|
471
473
|
let r, t, n, o;
|
|
472
474
|
const i = {}, l = {};
|
|
473
475
|
for (let s = 0; s < e.length; s++) {
|
|
@@ -532,22 +534,22 @@ function $e(e) {
|
|
|
532
534
|
sourceMapPath: o
|
|
533
535
|
};
|
|
534
536
|
}
|
|
535
|
-
async function
|
|
536
|
-
const { options: r, output: t, docinfoPath: n, sourceMapPath: o } =
|
|
537
|
+
async function je(e) {
|
|
538
|
+
const { options: r, output: t, docinfoPath: n, sourceMapPath: o } = Ee(e);
|
|
537
539
|
n && (r.docinfo = await m(n, "utf8"));
|
|
538
|
-
const i = Date.now(), { html: l, sourceMap: s } = await
|
|
540
|
+
const i = Date.now(), { html: l, sourceMap: s } = await $e(r);
|
|
539
541
|
w.stderr.write(`pretext-html: rendered in ${Date.now() - i}ms
|
|
540
|
-
`), o && s && (await
|
|
541
|
-
`)), t ? (await
|
|
542
|
+
`), o && s && (await X(o, JSON.stringify(s, null, 2)), w.stderr.write(`pretext-html: wrote ${o}
|
|
543
|
+
`)), t ? (await X(t, l), w.stderr.write(`pretext-html: wrote ${t}
|
|
542
544
|
`)) : w.stdout.write(l);
|
|
543
545
|
}
|
|
544
546
|
export {
|
|
545
547
|
L as a,
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
548
|
+
pe as d,
|
|
549
|
+
De as f,
|
|
550
|
+
me as i,
|
|
551
|
+
je as m,
|
|
552
|
+
Ee as p,
|
|
553
|
+
$e as r,
|
|
552
554
|
U as x
|
|
553
555
|
};
|
package/dist/cli.d.ts
CHANGED
|
File without changes
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -3,4 +3,6 @@ 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';
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { d as i, f as
|
|
1
|
+
import { d as i, f as a, a as s, i as t, r as l, m, x as o } from "./cli-BQizBK0N.js";
|
|
2
|
+
import { PREVIEW_THEME_MESSAGE as p, injectThemeBridge as E, isPreviewTheme as d, previewThemeMessage as f, themeBridgeScript as c } from "./theme.js";
|
|
2
3
|
export {
|
|
4
|
+
p as PREVIEW_THEME_MESSAGE,
|
|
3
5
|
i as defaultXslDir,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
t as
|
|
8
|
-
|
|
6
|
+
a as findSourceMapEntry,
|
|
7
|
+
s as forcePortablePublication,
|
|
8
|
+
E as injectThemeBridge,
|
|
9
|
+
t as isJspiAvailable,
|
|
10
|
+
d as isPreviewTheme,
|
|
11
|
+
f as previewThemeMessage,
|
|
12
|
+
l as renderHtml,
|
|
13
|
+
m as runCli,
|
|
14
|
+
c as themeBridgeScript,
|
|
9
15
|
o as xpathStringLiteral
|
|
10
16
|
};
|
package/dist/mounts.d.ts
CHANGED
|
File without changes
|
package/dist/publication.d.ts
CHANGED
|
File without changes
|
package/dist/renderer.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PtxSourceMap } from './sourcemap.js';
|
|
2
|
+
import { PreviewTheme } from './theme.js';
|
|
2
3
|
export interface RenderOptions {
|
|
3
4
|
/** Path to the root PreTeXt source file (typically source/main.ptx). */
|
|
4
5
|
sourcePath: string;
|
|
@@ -61,6 +62,15 @@ export interface RenderOptions {
|
|
|
61
62
|
* sourcemap.ts for the id contract with pretext-assembly.xsl.
|
|
62
63
|
*/
|
|
63
64
|
sourceMap?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Let the embedding app control the preview's light/dark theme. When set, a
|
|
67
|
+
* small bridge script is injected into the page that applies this value as
|
|
68
|
+
* the initial theme and then follows `postMessage`s from the embedder (see
|
|
69
|
+
* `previewThemeMessage` / theme.ts). Omit to leave the page's native
|
|
70
|
+
* behaviour (localStorage + `prefers-color-scheme`) untouched — the output
|
|
71
|
+
* is then byte-identical to a render without this option.
|
|
72
|
+
*/
|
|
73
|
+
theme?: PreviewTheme;
|
|
64
74
|
}
|
|
65
75
|
export interface RenderResult {
|
|
66
76
|
/** Complete standalone HTML page (CDN-hosted css/js/MathJax). */
|
package/dist/sourcemap.d.ts
CHANGED
|
File without changes
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime light/dark theme control for rendered previews.
|
|
3
|
+
*
|
|
4
|
+
* A rendered PreTeXt page already knows how to switch between light and dark
|
|
5
|
+
* — pretext-core.js exposes a global `window.setDarkMode(isDark)` — but it
|
|
6
|
+
* only ever decides *which* to use from `localStorage` and the browser's
|
|
7
|
+
* `prefers-color-scheme`. Neither reflects the surroundings an embedder cares
|
|
8
|
+
* about: "VS Code is using a dark editor theme", "pretext.plus is in dark
|
|
9
|
+
* mode". This module lets the embedding app drive the preview's theme instead.
|
|
10
|
+
*
|
|
11
|
+
* It is entirely opt-in, controlled by `RenderOptions.theme`. When set, the
|
|
12
|
+
* renderer injects the small script produced by {@link themeBridgeScript},
|
|
13
|
+
* which:
|
|
14
|
+
*
|
|
15
|
+
* 1. applies an *initial* theme baked into the page (so an explicit dark
|
|
16
|
+
* preview does not flash light first), and
|
|
17
|
+
* 2. listens for a `postMessage` from the embedder and re-applies the theme
|
|
18
|
+
* live — no re-render needed.
|
|
19
|
+
*
|
|
20
|
+
* The embedder posts {@link previewThemeMessage}`(theme)` to the preview's
|
|
21
|
+
* window (a VS Code webview, an `<iframe>`'s `contentWindow`, or the page's
|
|
22
|
+
* own `window` for an inline render). This module has no runtime dependencies,
|
|
23
|
+
* so an embedder can import just the protocol (`@pretextbook/pretext-html/theme`)
|
|
24
|
+
* without pulling in the WASM renderer.
|
|
25
|
+
*
|
|
26
|
+
* Timing note: `window.setDarkMode` is defined by pretext-core.js only inside
|
|
27
|
+
* its `DOMContentLoaded` handler, so the injected script cannot assume it
|
|
28
|
+
* exists yet — it retries on `DOMContentLoaded`/`load` and remembers the last
|
|
29
|
+
* requested theme on `window` so it survives the extension's in-place
|
|
30
|
+
* `document.write` rebuilds.
|
|
31
|
+
*/
|
|
32
|
+
export type PreviewTheme = "dark" | "light" | "system";
|
|
33
|
+
/**
|
|
34
|
+
* The `type` field of the message an embedder posts to drive the preview's
|
|
35
|
+
* theme. Namespaced so it does not collide with an embedder's own messages.
|
|
36
|
+
*/
|
|
37
|
+
export declare const PREVIEW_THEME_MESSAGE = "pretext-html:set-theme";
|
|
38
|
+
export interface PreviewThemeMessage {
|
|
39
|
+
type: typeof PREVIEW_THEME_MESSAGE;
|
|
40
|
+
theme: PreviewTheme;
|
|
41
|
+
}
|
|
42
|
+
/** True when `value` is one of the three {@link PreviewTheme} strings. */
|
|
43
|
+
export declare function isPreviewTheme(value: unknown): value is PreviewTheme;
|
|
44
|
+
/**
|
|
45
|
+
* Build the message an embedder posts to a rendered preview to set its theme.
|
|
46
|
+
* Send it with `webview.postMessage(...)` (VS Code), `iframe.contentWindow
|
|
47
|
+
* .postMessage(..., "*")` (embedded), or `window.postMessage(...)` (inline).
|
|
48
|
+
*/
|
|
49
|
+
export declare function previewThemeMessage(theme: PreviewTheme): PreviewThemeMessage;
|
|
50
|
+
/**
|
|
51
|
+
* The inline `<script>` (as a string) that wires a rendered page to the
|
|
52
|
+
* embedder's theme. Injected into the page `<head>` by the renderer when
|
|
53
|
+
* `RenderOptions.theme` is set; `initial` is baked in as the starting theme.
|
|
54
|
+
*
|
|
55
|
+
* Written in ES5-ish, self-contained JS because it is embedded verbatim in the
|
|
56
|
+
* output page (no bundler runs over it) and re-executes on every in-place
|
|
57
|
+
* `document.write` rebuild. It is idempotent: handlers are keyed on `window`
|
|
58
|
+
* and removed before being re-added, and the last requested theme persists on
|
|
59
|
+
* `window` so a rebuilt document re-applies it rather than snapping back to
|
|
60
|
+
* `initial`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function themeBridgeScript(initial: PreviewTheme): string;
|
|
63
|
+
/**
|
|
64
|
+
* Inject the theme bridge script into a rendered HTML page's `<head>` (as
|
|
65
|
+
* early as possible, to minimise any flash). Returns the page unchanged when
|
|
66
|
+
* it has no recognisable `<head>`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function injectThemeBridge(html: string, theme: PreviewTheme): string;
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const n = "pretext-html:set-theme";
|
|
2
|
+
function i(e) {
|
|
3
|
+
return e === "dark" || e === "light" || e === "system";
|
|
4
|
+
}
|
|
5
|
+
function d(e) {
|
|
6
|
+
return { type: n, theme: e };
|
|
7
|
+
}
|
|
8
|
+
function a(e) {
|
|
9
|
+
return [
|
|
10
|
+
"<script>",
|
|
11
|
+
"(function () {",
|
|
12
|
+
" var CFG = " + JSON.stringify({ msg: n, initial: e }) + ";",
|
|
13
|
+
// Where the last requested theme is remembered so it survives an in-place
|
|
14
|
+
// document rewrite (same Window) and outranks the baked initial value.
|
|
15
|
+
" var KEY = '__ptxPreviewTheme';",
|
|
16
|
+
" var MEDIA = '(prefers-color-scheme: dark)';",
|
|
17
|
+
" function isTheme(v) {",
|
|
18
|
+
" return v === 'dark' || v === 'light' || v === 'system';",
|
|
19
|
+
" }",
|
|
20
|
+
" function prefersDark() {",
|
|
21
|
+
" return !!(window.matchMedia && window.matchMedia(MEDIA).matches);",
|
|
22
|
+
" }",
|
|
23
|
+
" function resolveDark(theme) {",
|
|
24
|
+
" if (theme === 'dark') return true;",
|
|
25
|
+
" if (theme === 'light') return false;",
|
|
26
|
+
" return prefersDark();",
|
|
27
|
+
// "system"
|
|
28
|
+
" }",
|
|
29
|
+
" function current() {",
|
|
30
|
+
" return isTheme(window[KEY]) ? window[KEY] : CFG.initial;",
|
|
31
|
+
" }",
|
|
32
|
+
// A theme with no dark variant marks the root data-darkmode="disabled";
|
|
33
|
+
// never force dark mode on in that case (mirrors setDarkMode's own guard).
|
|
34
|
+
" function darkModeDisabled() {",
|
|
35
|
+
" var el = document.documentElement;",
|
|
36
|
+
" return !!(el && el.dataset && el.dataset.darkmode === 'disabled');",
|
|
37
|
+
" }",
|
|
38
|
+
" function apply(theme) {",
|
|
39
|
+
" window[KEY] = theme;",
|
|
40
|
+
" if (darkModeDisabled()) return;",
|
|
41
|
+
" var dark = resolveDark(theme);",
|
|
42
|
+
// Toggle the class setDarkMode would set, right now, so an explicit theme
|
|
43
|
+
// does not flash before pretext-core.js defines setDarkMode. setDarkMode
|
|
44
|
+
// (once available) then does the complete job, including iframes.
|
|
45
|
+
" var el = document.documentElement;",
|
|
46
|
+
" if (el && el.classList) { el.classList.toggle('dark-mode', dark); }",
|
|
47
|
+
" if (typeof window.setDarkMode === 'function') { window.setDarkMode(dark); }",
|
|
48
|
+
" }",
|
|
49
|
+
" function reapply() { apply(current()); }",
|
|
50
|
+
// Immediately (no-op until setDarkMode exists), then again once the page's
|
|
51
|
+
// own script has defined it.
|
|
52
|
+
" reapply();",
|
|
53
|
+
" document.addEventListener('DOMContentLoaded', reapply);",
|
|
54
|
+
" window.addEventListener('load', reapply);",
|
|
55
|
+
// Embedder -> preview live updates.
|
|
56
|
+
" if (window.__ptxThemeMsgHandler) {",
|
|
57
|
+
" window.removeEventListener('message', window.__ptxThemeMsgHandler);",
|
|
58
|
+
" }",
|
|
59
|
+
" window.__ptxThemeMsgHandler = function (event) {",
|
|
60
|
+
" var data = event && event.data;",
|
|
61
|
+
" if (data && data.type === CFG.msg && isTheme(data.theme)) {",
|
|
62
|
+
" apply(data.theme);",
|
|
63
|
+
" }",
|
|
64
|
+
" };",
|
|
65
|
+
" window.addEventListener('message', window.__ptxThemeMsgHandler);",
|
|
66
|
+
// Track OS changes while following the system theme.
|
|
67
|
+
" if (window.matchMedia) {",
|
|
68
|
+
" var mq = window.matchMedia(MEDIA);",
|
|
69
|
+
" if (window.__ptxThemeMediaHandler) {",
|
|
70
|
+
" try { mq.removeEventListener('change', window.__ptxThemeMediaHandler); } catch (e) {}",
|
|
71
|
+
" }",
|
|
72
|
+
" window.__ptxThemeMediaHandler = function () {",
|
|
73
|
+
" if (current() === 'system') { reapply(); }",
|
|
74
|
+
" };",
|
|
75
|
+
" try { mq.addEventListener('change', window.__ptxThemeMediaHandler); } catch (e) {}",
|
|
76
|
+
" }",
|
|
77
|
+
"})();",
|
|
78
|
+
"<\/script>"
|
|
79
|
+
].join(`
|
|
80
|
+
`);
|
|
81
|
+
}
|
|
82
|
+
function o(e, t) {
|
|
83
|
+
const r = a(t);
|
|
84
|
+
return /<head[^>]*>/i.test(e) ? e.replace(/<head([^>]*)>/i, `<head$1>
|
|
85
|
+
${r}`) : e;
|
|
86
|
+
}
|
|
87
|
+
export {
|
|
88
|
+
n as PREVIEW_THEME_MESSAGE,
|
|
89
|
+
o as injectThemeBridge,
|
|
90
|
+
i as isPreviewTheme,
|
|
91
|
+
d as previewThemeMessage,
|
|
92
|
+
a as themeBridgeScript
|
|
93
|
+
};
|
package/dist/xinclude.d.ts
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pretextbook/pretext-html",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Convert PreTeXt documents to HTML in pure JavaScript using the official PreTeXt XSLT stylesheets via libxslt-wasm. No Python or PreTeXt installation required.",
|
|
5
5
|
"author": "Oscar Levin",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
"type": "module",
|
|
17
17
|
"main": "./dist/index.js",
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
|
+
"typesVersions": {
|
|
20
|
+
"*": {
|
|
21
|
+
"theme": [
|
|
22
|
+
"./dist/theme.d.ts"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
19
26
|
"bin": {
|
|
20
27
|
"pretext-html": "./cli.mjs"
|
|
21
28
|
},
|
|
@@ -25,6 +32,11 @@
|
|
|
25
32
|
"import": "./dist/index.js",
|
|
26
33
|
"default": "./dist/index.js"
|
|
27
34
|
},
|
|
35
|
+
"./theme": {
|
|
36
|
+
"types": "./dist/theme.d.ts",
|
|
37
|
+
"import": "./dist/theme.js",
|
|
38
|
+
"default": "./dist/theme.js"
|
|
39
|
+
},
|
|
28
40
|
"./cli": "./dist/cli.js"
|
|
29
41
|
},
|
|
30
42
|
"sideEffects": false,
|
|
@@ -44,7 +56,7 @@
|
|
|
44
56
|
"xast-util-to-xml": "^4.0.0"
|
|
45
57
|
},
|
|
46
58
|
"engines": {
|
|
47
|
-
"node": ">=
|
|
59
|
+
"node": ">=24"
|
|
48
60
|
},
|
|
49
61
|
"publishConfig": {
|
|
50
62
|
"access": "public"
|