@pretextbook/pretext-html 0.2.0 → 0.4.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.
- package/README.md +37 -6
- package/assets/preview-html.xsl +8 -4
- package/assets/upstream.json +1 -1
- package/assets/xsl/README.md +25 -24
- package/assets/xsl/entities.ent +20 -0
- package/assets/xsl/extract-biblio-csl.xsl +1 -1
- package/assets/xsl/extract-pg.xsl +111 -297
- package/assets/xsl/extract-qrcode.xsl +11 -1
- package/assets/xsl/extract-sageplot.xsl +1 -1
- package/assets/xsl/latex/pretext-latex-texstyle.xsl +1 -2
- package/assets/xsl/localizations/README.md +24 -24
- package/assets/xsl/pretext-assembly.xsl +101 -11
- package/assets/xsl/pretext-beamer.xsl +43 -146
- package/assets/xsl/pretext-braille-preprint.xsl +457 -201
- package/assets/xsl/pretext-common.xsl +388 -423
- package/assets/xsl/pretext-epub.xsl +301 -72
- package/assets/xsl/pretext-fo.xsl +70 -86
- package/assets/xsl/pretext-html.xsl +331 -259
- package/assets/xsl/pretext-jupyter.xsl +534 -322
- package/assets/xsl/pretext-latex-classic.xsl +14 -15
- package/assets/xsl/pretext-latex-common.xsl +385 -2389
- package/assets/xsl/pretext-latex.xsl +1995 -5
- package/assets/xsl/pretext-markdown.xsl +919 -0
- package/assets/xsl/pretext-numbers.xsl +22 -4
- package/assets/xsl/pretext-revealjs.xsl +241 -33
- package/assets/xsl/pretext-runestone-fitb.xsl +20 -22
- package/assets/xsl/pretext-runestone.xsl +3 -3
- package/assets/xsl/pretext-sage-doctest.xsl +2 -2
- package/assets/xsl/pretext-text-utilities.xsl +69 -1
- package/assets/xsl/pretext-text.xsl +1077 -107
- package/assets/xsl/publisher-variables.xsl +396 -452
- package/assets/xsl/support/play-button/README.md +1 -3
- package/assets/xsl/tests/README.md +1 -1
- package/assets/xsl/utilities/README.md +6 -8
- package/assets/xsl/utilities/report-publisher-variables.xsl +15 -0
- package/assets/xsl-bundle.json +1 -1
- package/dist/assets.d.ts +43 -0
- package/dist/assets.js +76 -0
- package/dist/cli-Cp6C0sif.js +654 -0
- package/dist/cli.js +1 -1
- package/dist/index.browser.js +367 -307
- package/dist/index.d.ts +5 -0
- package/dist/index.js +16 -11
- package/dist/missing-asset.d.ts +31 -0
- package/dist/publication.d.ts +36 -1
- package/dist/renderer.d.ts +49 -0
- package/package.json +9 -1
- package/dist/cli-B2LiKunq.js +0 -588
package/dist/cli-B2LiKunq.js
DELETED
|
@@ -1,588 +0,0 @@
|
|
|
1
|
-
import { readFile as S, writeFile as L } from "node:fs/promises";
|
|
2
|
-
import * as m from "node:process";
|
|
3
|
-
import * as l from "node:path";
|
|
4
|
-
import { fileURLToPath as re } from "node:url";
|
|
5
|
-
import { fromXml as v } from "xast-util-from-xml";
|
|
6
|
-
import { toXml as y } from "xast-util-to-xml";
|
|
7
|
-
import { injectThemeBridge as ne } from "./theme.js";
|
|
8
|
-
async function N(e, r) {
|
|
9
|
-
const t = l.resolve(e), n = l.resolve(t, `.${l.posix.normalize(r)}`);
|
|
10
|
-
if (n !== t && !n.startsWith(t + l.sep)) {
|
|
11
|
-
console.error(
|
|
12
|
-
`pretext-html: refusing to serve ${r} from outside ${t}`
|
|
13
|
-
);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
try {
|
|
17
|
-
return new Uint8Array(await S(n));
|
|
18
|
-
} catch {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
async function I(e) {
|
|
23
|
-
try {
|
|
24
|
-
return await S(e, "utf8");
|
|
25
|
-
} catch {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
let _;
|
|
30
|
-
function Fe(e) {
|
|
31
|
-
_ = e;
|
|
32
|
-
}
|
|
33
|
-
function k() {
|
|
34
|
-
return _ ?? process.env.PRETEXT_HTML_ASSETS ?? l.resolve(l.dirname(re(import.meta.url)), "..", "assets");
|
|
35
|
-
}
|
|
36
|
-
function oe(e, r) {
|
|
37
|
-
return l.join(e, r);
|
|
38
|
-
}
|
|
39
|
-
const D = /* @__PURE__ */ new Map(), H = /* @__PURE__ */ new Map();
|
|
40
|
-
let T, ie = 0, J = N;
|
|
41
|
-
function Re(e) {
|
|
42
|
-
J = e;
|
|
43
|
-
}
|
|
44
|
-
function se(e, r) {
|
|
45
|
-
const t = typeof e == "string" ? e : e instanceof URL ? e.href : e.url, n = H.get(t);
|
|
46
|
-
if (n !== void 0)
|
|
47
|
-
return Promise.resolve(new Response(n, { status: 200 }));
|
|
48
|
-
let o;
|
|
49
|
-
try {
|
|
50
|
-
o = new URL(t).host;
|
|
51
|
-
} catch {
|
|
52
|
-
o = "";
|
|
53
|
-
}
|
|
54
|
-
const i = D.get(o);
|
|
55
|
-
return i !== void 0 ? ce(i, t) : T(e, r);
|
|
56
|
-
}
|
|
57
|
-
const ae = '<?xml version="1.0"?><pretext-preview-missing-file/>';
|
|
58
|
-
async function ce(e, r) {
|
|
59
|
-
const t = decodeURIComponent(new URL(r).pathname), n = await J(e, t);
|
|
60
|
-
if (n === void 0)
|
|
61
|
-
return new Response(ae, { status: 200 });
|
|
62
|
-
const o = typeof n == "string" ? n : new Uint8Array(n);
|
|
63
|
-
return new Response(o, { status: 200 });
|
|
64
|
-
}
|
|
65
|
-
function q() {
|
|
66
|
-
T || (T = globalThis.fetch, globalThis.fetch = se);
|
|
67
|
-
}
|
|
68
|
-
function z(e) {
|
|
69
|
-
q();
|
|
70
|
-
const r = `mnt${++ie}.ptx.invalid`;
|
|
71
|
-
return D.set(r, e), `http://${r}`;
|
|
72
|
-
}
|
|
73
|
-
function le(e) {
|
|
74
|
-
D.delete(new URL(e).host);
|
|
75
|
-
}
|
|
76
|
-
function ue(e, r) {
|
|
77
|
-
q(), H.set(e, r);
|
|
78
|
-
}
|
|
79
|
-
const fe = `<?xml version="1.0" encoding="UTF-8"?>
|
|
80
|
-
<publication>
|
|
81
|
-
<source>
|
|
82
|
-
<directories external="../assets" generated="../generated-assets" />
|
|
83
|
-
</source>
|
|
84
|
-
<html>
|
|
85
|
-
<platform portable="yes"/>
|
|
86
|
-
</html>
|
|
87
|
-
</publication>
|
|
88
|
-
`;
|
|
89
|
-
function G(e, r) {
|
|
90
|
-
for (const t of e.children)
|
|
91
|
-
if (t.type === "element" && t.name === r)
|
|
92
|
-
return t;
|
|
93
|
-
}
|
|
94
|
-
function F(e, r) {
|
|
95
|
-
let t = G(e, r);
|
|
96
|
-
return t || (t = { type: "element", name: r, attributes: {}, children: [] }, e.children.push(t)), t;
|
|
97
|
-
}
|
|
98
|
-
function R(e) {
|
|
99
|
-
if (!e)
|
|
100
|
-
return fe;
|
|
101
|
-
const r = v(e), t = G(r, "publication");
|
|
102
|
-
if (!t)
|
|
103
|
-
throw new Error(
|
|
104
|
-
"Invalid publication file: no root <publication> element found"
|
|
105
|
-
);
|
|
106
|
-
const n = F(t, "html"), o = F(n, "platform");
|
|
107
|
-
return o.attributes = { ...o.attributes, portable: "yes" }, y(r);
|
|
108
|
-
}
|
|
109
|
-
const Y = "http://www.w3.org/2001/XInclude", A = 64;
|
|
110
|
-
async function de(e, r, t) {
|
|
111
|
-
return e.includes("include") ? (await V(e, r, t)).content : e;
|
|
112
|
-
}
|
|
113
|
-
async function V(e, r, t) {
|
|
114
|
-
const n = v(e), o = {
|
|
115
|
-
projectDir: l.resolve(t),
|
|
116
|
-
stack: [l.resolve(r)]
|
|
117
|
-
}, i = await g(
|
|
118
|
-
n,
|
|
119
|
-
l.dirname(l.resolve(r)),
|
|
120
|
-
{ "": "" },
|
|
121
|
-
o
|
|
122
|
-
);
|
|
123
|
-
return { tree: n, content: i ? y(n) : e };
|
|
124
|
-
}
|
|
125
|
-
function he(e) {
|
|
126
|
-
return e.data?.ptxIncludedFile;
|
|
127
|
-
}
|
|
128
|
-
function pe(e, r) {
|
|
129
|
-
const t = e.data ?? (e.data = {});
|
|
130
|
-
t.ptxIncludedFile = r;
|
|
131
|
-
}
|
|
132
|
-
function x(e, r) {
|
|
133
|
-
let t = e;
|
|
134
|
-
for (const [n, o] of Object.entries(r.attributes))
|
|
135
|
-
(n === "xmlns" || n.startsWith("xmlns:")) && (t === e && (t = { ...e }), t[n === "xmlns" ? "" : n.slice(6)] = o ?? "");
|
|
136
|
-
return t;
|
|
137
|
-
}
|
|
138
|
-
function Z(e, r) {
|
|
139
|
-
const t = e.name.indexOf(":"), n = t === -1 ? "" : e.name.slice(0, t);
|
|
140
|
-
return (t === -1 ? e.name : e.name.slice(t + 1)) === "include" && r[n] === Y;
|
|
141
|
-
}
|
|
142
|
-
async function g(e, r, t, n) {
|
|
143
|
-
let o = !1;
|
|
144
|
-
for (let i = 0; i < e.children.length; i++) {
|
|
145
|
-
const c = e.children[i];
|
|
146
|
-
if (c.type !== "element")
|
|
147
|
-
continue;
|
|
148
|
-
const s = x(t, c);
|
|
149
|
-
if (Z(c, s)) {
|
|
150
|
-
const u = await K(
|
|
151
|
-
c,
|
|
152
|
-
r,
|
|
153
|
-
s,
|
|
154
|
-
n
|
|
155
|
-
);
|
|
156
|
-
e.children.splice(i, 1, ...u), i += u.length - 1, o = !0;
|
|
157
|
-
} else await g(c, r, s, n) && (o = !0);
|
|
158
|
-
}
|
|
159
|
-
return o;
|
|
160
|
-
}
|
|
161
|
-
async function K(e, r, t, n) {
|
|
162
|
-
const o = n.stack[n.stack.length - 1];
|
|
163
|
-
if (e.attributes.xpointer)
|
|
164
|
-
throw new Error(
|
|
165
|
-
`xi:include with xpointer is not supported by the JS preview build (in ${o})`
|
|
166
|
-
);
|
|
167
|
-
const i = e.attributes.href;
|
|
168
|
-
if (!i)
|
|
169
|
-
throw new Error(`xi:include without href (in ${o})`);
|
|
170
|
-
let c = i;
|
|
171
|
-
try {
|
|
172
|
-
c = decodeURIComponent(i);
|
|
173
|
-
} catch {
|
|
174
|
-
}
|
|
175
|
-
const s = l.resolve(r, c);
|
|
176
|
-
if (s !== n.projectDir && !s.startsWith(n.projectDir + l.sep))
|
|
177
|
-
throw new Error(
|
|
178
|
-
`xi:include escapes the project directory: ${i} (in ${o})`
|
|
179
|
-
);
|
|
180
|
-
if (n.stack.includes(s))
|
|
181
|
-
throw new Error(
|
|
182
|
-
`Circular xi:include: ${[...n.stack, s].join(" -> ")}`
|
|
183
|
-
);
|
|
184
|
-
if (n.stack.length >= A)
|
|
185
|
-
throw new Error(`xi:include nesting exceeds ${A} levels`);
|
|
186
|
-
const u = await I(s);
|
|
187
|
-
if (u === void 0) {
|
|
188
|
-
const f = we(e, t);
|
|
189
|
-
if (f)
|
|
190
|
-
return await g(f, r, t, n), f.children;
|
|
191
|
-
throw new Error(`xi:include target not found: ${i} (in ${o})`);
|
|
192
|
-
}
|
|
193
|
-
if (e.attributes.parse === "text")
|
|
194
|
-
return [{ type: "text", value: u }];
|
|
195
|
-
let a;
|
|
196
|
-
try {
|
|
197
|
-
a = v(u);
|
|
198
|
-
} catch (f) {
|
|
199
|
-
throw new Error(
|
|
200
|
-
`Could not parse xi:include target ${s} as XML: ${f instanceof Error ? f.message : f}. (Included files must be well-formed, with a single root element.)`
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
n.stack.push(s);
|
|
204
|
-
try {
|
|
205
|
-
await g(a, l.dirname(s), { "": "" }, n);
|
|
206
|
-
} finally {
|
|
207
|
-
n.stack.pop();
|
|
208
|
-
}
|
|
209
|
-
const d = a.children.filter(
|
|
210
|
-
(f) => f.type === "element"
|
|
211
|
-
);
|
|
212
|
-
for (const f of d)
|
|
213
|
-
pe(f, s);
|
|
214
|
-
return d;
|
|
215
|
-
}
|
|
216
|
-
function U(e) {
|
|
217
|
-
return e.name === "docinfo";
|
|
218
|
-
}
|
|
219
|
-
async function me(e, r, t) {
|
|
220
|
-
try {
|
|
221
|
-
const o = v(e).children.find(
|
|
222
|
-
(a) => a.type === "element"
|
|
223
|
-
);
|
|
224
|
-
if (!o)
|
|
225
|
-
return;
|
|
226
|
-
const i = l.resolve(r), c = l.dirname(i), s = {
|
|
227
|
-
projectDir: l.resolve(t),
|
|
228
|
-
stack: [i]
|
|
229
|
-
}, u = x({ "": "" }, o);
|
|
230
|
-
for (const a of o.children) {
|
|
231
|
-
if (a.type !== "element")
|
|
232
|
-
continue;
|
|
233
|
-
const d = x(u, a);
|
|
234
|
-
if (U(a))
|
|
235
|
-
return await g(a, c, d, s), y(a);
|
|
236
|
-
if (Z(a, d)) {
|
|
237
|
-
const p = (await K(
|
|
238
|
-
a,
|
|
239
|
-
c,
|
|
240
|
-
d,
|
|
241
|
-
s
|
|
242
|
-
)).find(
|
|
243
|
-
(w) => w.type === "element" && U(w)
|
|
244
|
-
);
|
|
245
|
-
if (p)
|
|
246
|
-
return y(p);
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
return;
|
|
252
|
-
} catch {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
function we(e, r) {
|
|
257
|
-
for (const t of e.children) {
|
|
258
|
-
if (t.type !== "element")
|
|
259
|
-
continue;
|
|
260
|
-
const n = x(r, t), o = t.name.indexOf(":"), i = o === -1 ? "" : t.name.slice(0, o);
|
|
261
|
-
if ((o === -1 ? t.name : t.name.slice(o + 1)) === "fallback" && n[i] === Y)
|
|
262
|
-
return t;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
function Q(e) {
|
|
266
|
-
return typeof e == "object" && e !== null && e.type === "element";
|
|
267
|
-
}
|
|
268
|
-
function be(e) {
|
|
269
|
-
return /^(pf|xhtml):/.test(e.name);
|
|
270
|
-
}
|
|
271
|
-
function ge(e, r, t) {
|
|
272
|
-
const n = [], o = e.children.find(Q);
|
|
273
|
-
if (o) {
|
|
274
|
-
const i = t?.parentId ?? "root";
|
|
275
|
-
ee(o, i, t?.position ?? 1, r, i, n);
|
|
276
|
-
}
|
|
277
|
-
return n;
|
|
278
|
-
}
|
|
279
|
-
function ee(e, r, t, n, o, i) {
|
|
280
|
-
const c = he(e) ?? n;
|
|
281
|
-
let s, u;
|
|
282
|
-
if (be(e))
|
|
283
|
-
u = "root";
|
|
284
|
-
else {
|
|
285
|
-
const d = e.attributes.label ?? e.attributes["xml:id"];
|
|
286
|
-
s = d ?? `${r}-${t}`, i.push({
|
|
287
|
-
id: s,
|
|
288
|
-
file: c,
|
|
289
|
-
line: e.position?.start.line ?? 1,
|
|
290
|
-
column: e.position?.start.column ?? 1,
|
|
291
|
-
endLine: e.position?.end.line ?? e.position?.start.line ?? 1,
|
|
292
|
-
parent: o
|
|
293
|
-
}), u = s;
|
|
294
|
-
}
|
|
295
|
-
let a = 0;
|
|
296
|
-
for (const d of e.children)
|
|
297
|
-
Q(d) && (a += 1, ee(
|
|
298
|
-
d,
|
|
299
|
-
u,
|
|
300
|
-
a,
|
|
301
|
-
c,
|
|
302
|
-
s ?? o,
|
|
303
|
-
i
|
|
304
|
-
));
|
|
305
|
-
}
|
|
306
|
-
function Ae(e, r) {
|
|
307
|
-
let t;
|
|
308
|
-
for (const n of e)
|
|
309
|
-
n.line <= r && (t = n);
|
|
310
|
-
return t ?? e[0];
|
|
311
|
-
}
|
|
312
|
-
function ye() {
|
|
313
|
-
return oe(k(), "xsl");
|
|
314
|
-
}
|
|
315
|
-
function xe() {
|
|
316
|
-
return "Suspending" in WebAssembly;
|
|
317
|
-
}
|
|
318
|
-
function ve() {
|
|
319
|
-
if (!xe())
|
|
320
|
-
throw new Error(
|
|
321
|
-
"WebAssembly JSPI is not enabled. Run Node with --experimental-wasm-jspi (or use the pretext-html CLI, which re-launches itself with the flag)."
|
|
322
|
-
);
|
|
323
|
-
}
|
|
324
|
-
function C(e) {
|
|
325
|
-
return e.includes("'") ? e.includes('"') ? `concat(${e.split("'").map((t) => `'${t}'`).join(`, "'", `)})` : `"${e}"` : `'${e}'`;
|
|
326
|
-
}
|
|
327
|
-
function Ee(e) {
|
|
328
|
-
return e.replace(
|
|
329
|
-
/from '\.\/(https:\/\/[^']+)'/g,
|
|
330
|
-
(r, t) => `from '${t}'`
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
function $e(e) {
|
|
334
|
-
return e.slice(0, 65536).replace(/<\?[\s\S]*?\?>/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<!DOCTYPE[^>]*>/gi, " ").match(/<\s*([A-Za-z][\w:-]*)/)?.[1];
|
|
335
|
-
}
|
|
336
|
-
async function O(e) {
|
|
337
|
-
const r = await I(e);
|
|
338
|
-
if (r === void 0)
|
|
339
|
-
throw new Error(
|
|
340
|
-
`Could not read ${e}. (In the browser build only absolute URLs are readable — pass sourceContent instead of relying on sourcePath.)`
|
|
341
|
-
);
|
|
342
|
-
return r;
|
|
343
|
-
}
|
|
344
|
-
async function Pe(e, r) {
|
|
345
|
-
const t = l.resolve(e), n = await I(t);
|
|
346
|
-
if (n !== void 0)
|
|
347
|
-
return me(n, t, r);
|
|
348
|
-
}
|
|
349
|
-
function ke(e, r, t) {
|
|
350
|
-
const n = e.replace(/^\uFEFF/, "").replace(/<\?xml[\s\S]*?\?>/, "").replace(/<!DOCTYPE[^>]*>/i, ""), o = r === "chapter" || r === "part" ? "book" : "article";
|
|
351
|
-
return `<pretext>
|
|
352
|
-
${t?.trim() ? `${t.trim()}
|
|
353
|
-
` : ""}<${o}>
|
|
354
|
-
<title/>
|
|
355
|
-
${n}
|
|
356
|
-
</${o}>
|
|
357
|
-
</pretext>
|
|
358
|
-
`;
|
|
359
|
-
}
|
|
360
|
-
function B(e) {
|
|
361
|
-
if (e instanceof Error && /memory access|out of bounds/i.test(e.message))
|
|
362
|
-
throw new Error(
|
|
363
|
-
"The document is too large for the current WebAssembly build (stack overflow). Whole-book builds are a known limitation; try a smaller document, or see the README about rebuilding libxslt-wasm with a larger stack.",
|
|
364
|
-
{ cause: e }
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
let $;
|
|
368
|
-
async function te() {
|
|
369
|
-
return $ || ($ = (async () => {
|
|
370
|
-
const [e, r] = await Promise.all([
|
|
371
|
-
import("@pretextbook/libxslt-wasm"),
|
|
372
|
-
import("@pretextbook/libxslt-wasm/exslt")
|
|
373
|
-
]);
|
|
374
|
-
return r.registerAll(), e;
|
|
375
|
-
})()), $;
|
|
376
|
-
}
|
|
377
|
-
const P = /* @__PURE__ */ new Map();
|
|
378
|
-
async function Te(e) {
|
|
379
|
-
const r = e;
|
|
380
|
-
let t = P.get(r);
|
|
381
|
-
return t || (t = (async () => {
|
|
382
|
-
const { XmlDocument: n, XsltStylesheet: o } = await te(), i = z(r), c = await N(
|
|
383
|
-
k(),
|
|
384
|
-
"/preview-html.xsl"
|
|
385
|
-
);
|
|
386
|
-
if (c === void 0)
|
|
387
|
-
throw new Error(
|
|
388
|
-
`Could not read preview-html.xsl from ${k()}. Check the assets location (PRETEXT_HTML_ASSETS under Node, setAssetsBase() in the browser).`
|
|
389
|
-
);
|
|
390
|
-
const s = new TextDecoder().decode(c), u = await n.fromString(s, {
|
|
391
|
-
url: `${i}/preview-html.xsl`,
|
|
392
|
-
options: { noEnt: !0, dtdLoad: !0, huge: !0 }
|
|
393
|
-
});
|
|
394
|
-
return o.fromXmlDocument(u);
|
|
395
|
-
})(), P.set(r, t), t.catch(() => P.delete(r))), t;
|
|
396
|
-
}
|
|
397
|
-
async function Se(e) {
|
|
398
|
-
ve();
|
|
399
|
-
const { XmlDocument: r } = await te(), t = await Te(e.xslDir ?? ye()), n = l.resolve(e.sourcePath), o = l.resolve(
|
|
400
|
-
e.projectDir ?? l.dirname(n)
|
|
401
|
-
), i = e.sourceContent ?? await O(n), c = l.relative(o, n);
|
|
402
|
-
if (c.startsWith(".."))
|
|
403
|
-
throw new Error(
|
|
404
|
-
`sourcePath (${n}) must live inside projectDir (${o})`
|
|
405
|
-
);
|
|
406
|
-
const s = z(o);
|
|
407
|
-
try {
|
|
408
|
-
let u, a = `${s}/__pretext-preview-publication.xml`;
|
|
409
|
-
if (e.publicationPath) {
|
|
410
|
-
const h = l.resolve(e.publicationPath);
|
|
411
|
-
u = R(
|
|
412
|
-
await O(h)
|
|
413
|
-
);
|
|
414
|
-
const b = l.relative(o, h);
|
|
415
|
-
b.startsWith("..") || (a = `${s}/${b.split(l.sep).join("/")}`);
|
|
416
|
-
} else
|
|
417
|
-
u = R();
|
|
418
|
-
ue(a, u);
|
|
419
|
-
let d, f;
|
|
420
|
-
if (e.sourceMap) {
|
|
421
|
-
const h = await V(
|
|
422
|
-
i,
|
|
423
|
-
n,
|
|
424
|
-
o
|
|
425
|
-
);
|
|
426
|
-
d = h.tree, f = h.content;
|
|
427
|
-
} else
|
|
428
|
-
f = await de(
|
|
429
|
-
i,
|
|
430
|
-
n,
|
|
431
|
-
o
|
|
432
|
-
);
|
|
433
|
-
const p = $e(f);
|
|
434
|
-
let w = { parentId: "root", position: 1 };
|
|
435
|
-
if (p !== "pretext" && p !== "mathbook")
|
|
436
|
-
if (e.fragment) {
|
|
437
|
-
const h = e.docinfo ?? (e.docinfoSourcePath ? await Pe(e.docinfoSourcePath, o) : void 0);
|
|
438
|
-
f = ke(f, p, h), w = { parentId: h?.trim() ? "root-1-2" : "root-1-1", position: 2 };
|
|
439
|
-
} else
|
|
440
|
-
throw new Error(
|
|
441
|
-
`The document root is <${p ?? "?"}>, not <pretext> — this looks like an xi:included fragment. Render the project's main source file instead, or pass the fragment option.`
|
|
442
|
-
);
|
|
443
|
-
const M = d ? ge(d, n, w) : void 0, X = await r.fromString(f, {
|
|
444
|
-
url: `${s}/${c.split(l.sep).join("/")}`,
|
|
445
|
-
options: { noEnt: !0, dtdLoad: !0, huge: !0 }
|
|
446
|
-
}), j = {
|
|
447
|
-
publisher: C(a)
|
|
448
|
-
};
|
|
449
|
-
for (const [h, b] of Object.entries(e.stringParams ?? {}))
|
|
450
|
-
j[h] = C(b);
|
|
451
|
-
let E;
|
|
452
|
-
try {
|
|
453
|
-
E = await t.apply(X, j);
|
|
454
|
-
} catch (h) {
|
|
455
|
-
throw B(h), new Error(
|
|
456
|
-
"PreTeXt XSLT transform failed; see the PTX:ERROR/PTX:FATAL messages on stderr for details.",
|
|
457
|
-
{ cause: h }
|
|
458
|
-
);
|
|
459
|
-
} finally {
|
|
460
|
-
X.delete();
|
|
461
|
-
}
|
|
462
|
-
try {
|
|
463
|
-
let h = Ee(E.toHtmlString());
|
|
464
|
-
return e.theme && (h = ne(h, e.theme)), {
|
|
465
|
-
html: h,
|
|
466
|
-
...M ? { sourceMap: M } : {}
|
|
467
|
-
};
|
|
468
|
-
} catch (h) {
|
|
469
|
-
throw B(h), h;
|
|
470
|
-
} finally {
|
|
471
|
-
E.delete();
|
|
472
|
-
}
|
|
473
|
-
} finally {
|
|
474
|
-
le(s);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
const W = `Usage: pretext-html <source.ptx> [options]
|
|
478
|
-
|
|
479
|
-
Render a PreTeXt document to a single standalone HTML page (portable build:
|
|
480
|
-
one page, css/js/MathJax from CDN). No PreTeXt installation required.
|
|
481
|
-
|
|
482
|
-
Options:
|
|
483
|
-
-o, --output <file> Write HTML to a file instead of stdout
|
|
484
|
-
--publication <file> Publication file (portable html is forced on)
|
|
485
|
-
--project-dir <dir> Directory served to the transform for xi:includes
|
|
486
|
-
(default: the source file's directory)
|
|
487
|
-
--param <name=value> Extra XSLT string parameter (repeatable)
|
|
488
|
-
--xsl-dir <dir> Use PreTeXt stylesheets from this directory
|
|
489
|
-
instead of the vendored copy
|
|
490
|
-
--fragment Allow a non-root source file: wrap the fragment
|
|
491
|
-
in a minimal <pretext> document (an <article>,
|
|
492
|
-
or a <book> for <chapter>/<part> fragments)
|
|
493
|
-
--docinfo <file> File whose contents (a <docinfo> element) are
|
|
494
|
-
injected into the wrapper in --fragment mode, so
|
|
495
|
-
the fragment keeps the project's LaTeX macros
|
|
496
|
-
--docinfo-source <file> Complete source file (e.g. main.ptx) to lift the
|
|
497
|
-
<docinfo> from for --fragment mode, resolving
|
|
498
|
-
xi:includes (used when --docinfo is not given)
|
|
499
|
-
--source-map <file> Also write a JSON source map: HTML id → source
|
|
500
|
-
file/line for every element (for editor sync)
|
|
501
|
-
-h, --help Show this help
|
|
502
|
-
`;
|
|
503
|
-
function Ie(e) {
|
|
504
|
-
let r, t, n, o;
|
|
505
|
-
const i = {}, c = {};
|
|
506
|
-
for (let s = 0; s < e.length; s++) {
|
|
507
|
-
const u = e[s], a = () => {
|
|
508
|
-
if (s += 1, s >= e.length)
|
|
509
|
-
throw new Error(`Missing value for ${u}`);
|
|
510
|
-
return e[s];
|
|
511
|
-
};
|
|
512
|
-
switch (u) {
|
|
513
|
-
case "-h":
|
|
514
|
-
case "--help":
|
|
515
|
-
m.stdout.write(W), m.exit(0);
|
|
516
|
-
break;
|
|
517
|
-
case "-o":
|
|
518
|
-
case "--output":
|
|
519
|
-
t = a();
|
|
520
|
-
break;
|
|
521
|
-
case "--publication":
|
|
522
|
-
i.publicationPath = a();
|
|
523
|
-
break;
|
|
524
|
-
case "--project-dir":
|
|
525
|
-
i.projectDir = a();
|
|
526
|
-
break;
|
|
527
|
-
case "--xsl-dir":
|
|
528
|
-
i.xslDir = a();
|
|
529
|
-
break;
|
|
530
|
-
case "--fragment":
|
|
531
|
-
i.fragment = !0;
|
|
532
|
-
break;
|
|
533
|
-
case "--docinfo":
|
|
534
|
-
n = a();
|
|
535
|
-
break;
|
|
536
|
-
case "--docinfo-source":
|
|
537
|
-
i.docinfoSourcePath = a();
|
|
538
|
-
break;
|
|
539
|
-
case "--source-map":
|
|
540
|
-
o = a(), i.sourceMap = !0;
|
|
541
|
-
break;
|
|
542
|
-
case "--param": {
|
|
543
|
-
const d = a(), f = d.indexOf("=");
|
|
544
|
-
if (f === -1)
|
|
545
|
-
throw new Error(`--param expects name=value, got: ${d}`);
|
|
546
|
-
c[d.slice(0, f)] = d.slice(f + 1);
|
|
547
|
-
break;
|
|
548
|
-
}
|
|
549
|
-
default:
|
|
550
|
-
if (u.startsWith("-"))
|
|
551
|
-
throw new Error(`Unknown option: ${u}`);
|
|
552
|
-
if (r)
|
|
553
|
-
throw new Error(`Unexpected extra argument: ${u}`);
|
|
554
|
-
r = u;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
if (!r)
|
|
558
|
-
throw new Error(`No source file given.
|
|
559
|
-
|
|
560
|
-
` + W);
|
|
561
|
-
return Object.keys(c).length > 0 && (i.stringParams = c), {
|
|
562
|
-
options: { ...i, sourcePath: r },
|
|
563
|
-
output: t,
|
|
564
|
-
docinfoPath: n,
|
|
565
|
-
sourceMapPath: o
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
async function Ue(e) {
|
|
569
|
-
const { options: r, output: t, docinfoPath: n, sourceMapPath: o } = Ie(e);
|
|
570
|
-
n && (r.docinfo = await S(n, "utf8"));
|
|
571
|
-
const i = Date.now(), { html: c, sourceMap: s } = await Se(r);
|
|
572
|
-
m.stderr.write(`pretext-html: rendered in ${Date.now() - i}ms
|
|
573
|
-
`), o && s && (await L(o, JSON.stringify(s, null, 2)), m.stderr.write(`pretext-html: wrote ${o}
|
|
574
|
-
`)), t ? (await L(t, c), m.stderr.write(`pretext-html: wrote ${t}
|
|
575
|
-
`)) : m.stdout.write(c);
|
|
576
|
-
}
|
|
577
|
-
export {
|
|
578
|
-
R as a,
|
|
579
|
-
Re as b,
|
|
580
|
-
ye as d,
|
|
581
|
-
Ae as f,
|
|
582
|
-
xe as i,
|
|
583
|
-
Ue as m,
|
|
584
|
-
Ie as p,
|
|
585
|
-
Se as r,
|
|
586
|
-
Fe as s,
|
|
587
|
-
C as x
|
|
588
|
-
};
|