@danielsimonjr/sciengjs 0.9.0 → 1.0.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 +3 -2
- package/THIRD_PARTY_NOTICES.md +65 -4
- package/dist/browser/render.d.ts +13 -0
- package/dist/browser/render.js +10 -6
- package/dist/browser/render.js.map +1 -1
- package/dist/core.js +20 -12
- package/dist/core.js.map +1 -1
- package/dist/registry.d.ts +6 -0
- package/dist/registry.js +20 -0
- package/dist/registry.js.map +1 -1
- package/dist/tex/backend-pdf.d.ts +3 -0
- package/dist/tex/backend-pdf.js +10 -0
- package/dist/tex/backend-pdf.js.map +1 -0
- package/dist/tex/backend-png.d.ts +6 -0
- package/dist/tex/backend-png.js +19 -0
- package/dist/tex/backend-png.js.map +1 -0
- package/dist/tex/backend-svg.d.ts +3 -0
- package/dist/tex/backend-svg.js +8 -0
- package/dist/tex/backend-svg.js.map +1 -0
- package/dist/tex/bundles.d.ts +49 -0
- package/dist/tex/bundles.js +170 -0
- package/dist/tex/bundles.js.map +1 -0
- package/dist/tex/bundles.json +26 -0
- package/dist/tex/detect.d.ts +27 -0
- package/dist/tex/detect.js +212 -0
- package/dist/tex/detect.js.map +1 -0
- package/dist/tex/dvi.d.ts +44 -0
- package/dist/tex/dvi.js +280 -0
- package/dist/tex/dvi.js.map +1 -0
- package/dist/tex/host.d.ts +82 -0
- package/dist/tex/host.js +313 -0
- package/dist/tex/host.js.map +1 -0
- package/dist/tex/index.d.ts +16 -0
- package/dist/tex/index.js +17 -0
- package/dist/tex/index.js.map +1 -0
- package/dist/tex/render.d.ts +66 -0
- package/dist/tex/render.js +72 -0
- package/dist/tex/render.js.map +1 -0
- package/dist/tex/run.d.ts +51 -0
- package/dist/tex/run.js +54 -0
- package/dist/tex/run.js.map +1 -0
- package/dist/tex/specials.d.ts +32 -0
- package/dist/tex/specials.js +145 -0
- package/dist/tex/specials.js.map +1 -0
- package/dist/tex/stage.d.ts +34 -0
- package/dist/tex/stage.js +102 -0
- package/dist/tex/stage.js.map +1 -0
- package/dist/tex/tfm.d.ts +15 -0
- package/dist/tex/tfm.js +33 -0
- package/dist/tex/tfm.js.map +1 -0
- package/dist/tex/type1.d.ts +32 -0
- package/dist/tex/type1.js +402 -0
- package/dist/tex/type1.js.map +1 -0
- package/dist/tex/vfs.d.ts +37 -0
- package/dist/tex/vfs.js +80 -0
- package/dist/tex/vfs.js.map +1 -0
- package/dist/tex/wasm.d.ts +16 -0
- package/dist/tex/wasm.js +8 -0
- package/dist/tex/wasm.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/protocol.d.ts +6 -0
- package/package.json +110 -106
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { inflateRawSync } from "node:zlib";
|
|
6
|
+
import { RenderError } from "../errors.js";
|
|
7
|
+
import list from "./bundles.json" with { type: "json" };
|
|
8
|
+
/** The bundles of this build. `tools/tex/bundles.mjs` writes `bundles.json`, and CI fails when a built bundle differs from it. */
|
|
9
|
+
export const BUNDLES = list;
|
|
10
|
+
/** The sub-folder of the cache folder for the bundles. */
|
|
11
|
+
export const CACHE_SUBFOLDER = "tex-bundles";
|
|
12
|
+
const MAGIC = "SCTB1\0\0\0";
|
|
13
|
+
const sha256 = (b) => createHash("sha256").update(b).digest("hex");
|
|
14
|
+
/** The path of a bundle in the cache. */
|
|
15
|
+
export function cachePath(entry, settings) {
|
|
16
|
+
return path.join(settings.cacheDir, CACHE_SUBFOLDER, entry.file);
|
|
17
|
+
}
|
|
18
|
+
/** The download URL of a bundle. A base URL with no end slash gets one. */
|
|
19
|
+
export function bundleUrl(entry, settings) {
|
|
20
|
+
const base = settings.texBundleUrl;
|
|
21
|
+
return `${base.endsWith("/") ? base : `${base}/`}${entry.file}`;
|
|
22
|
+
}
|
|
23
|
+
/** Looks up a bundle of the list by name. A name that is not in the list is an internal error. */
|
|
24
|
+
export function findBundle(name, bundles = BUNDLES) {
|
|
25
|
+
const entry = bundles.find((b) => b.name === name);
|
|
26
|
+
if (entry === undefined)
|
|
27
|
+
throw new RenderError("E_INTERNAL", `the build has no TeX bundle named ${name}`);
|
|
28
|
+
return entry;
|
|
29
|
+
}
|
|
30
|
+
/** Reads a file or rejects with `undefined` when it is not there. */
|
|
31
|
+
async function readIfThere(file) {
|
|
32
|
+
try {
|
|
33
|
+
return new Uint8Array(await readFile(file));
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
if (e.code === "ENOENT")
|
|
37
|
+
return undefined;
|
|
38
|
+
throw e;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Downloads the bytes of a bundle from an `http:`, `https:` or `file:` URL. */
|
|
42
|
+
async function download(url, settings, entry) {
|
|
43
|
+
const fail = (why) => new RenderError("E_STAGE_MISSING", `the TeX bundle ${entry.name} is not available at ${url}: ${why}`);
|
|
44
|
+
let parsed;
|
|
45
|
+
try {
|
|
46
|
+
parsed = new URL(url);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
throw new RenderError("E_CONFIG", `texBundleUrl gives the URL ${url} for the TeX bundle ${entry.name}, and it is not a URL`);
|
|
50
|
+
}
|
|
51
|
+
if (parsed.protocol === "file:") {
|
|
52
|
+
try {
|
|
53
|
+
return new Uint8Array(await readFile(fileURLToPath(parsed)));
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
throw fail(e instanceof Error ? e.message : String(e));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:")
|
|
60
|
+
throw fail(`the protocol ${parsed.protocol} is not supported`);
|
|
61
|
+
try {
|
|
62
|
+
const res = await fetch(parsed, { redirect: "follow", signal: AbortSignal.timeout(settings.timeoutMs) });
|
|
63
|
+
if (!res.ok)
|
|
64
|
+
throw fail(`the server answered ${res.status}`);
|
|
65
|
+
const length = Number(res.headers.get("content-length") ?? 0);
|
|
66
|
+
if (length > entry.bytes)
|
|
67
|
+
throw new RenderError("E_INTEGRITY", `the TeX bundle ${entry.name} from ${url} is ${length} bytes, and the pin says ${entry.bytes}`);
|
|
68
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
if (e instanceof RenderError)
|
|
72
|
+
throw e;
|
|
73
|
+
throw fail(e instanceof Error ? e.message : String(e));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Returns the verified bytes of a bundle. The order is the cache, then the download.
|
|
78
|
+
* A cached file is hashed on every load. A cached file with a wrong hash is deleted, and the load goes on to the download.
|
|
79
|
+
* A download is allowed only when `allowNetwork` has `tex-bundles`. It goes to a temporary file in the cache folder,
|
|
80
|
+
* its hash and size are checked, and only then does a rename put it in place. A wrong hash deletes the temporary file and
|
|
81
|
+
* rejects with `E_INTEGRITY`, so a wrong file never stays in the cache. A bundle that is not cached, with the download not allowed,
|
|
82
|
+
* rejects with `E_STAGE_MISSING`.
|
|
83
|
+
*/
|
|
84
|
+
export async function loadBundleBytes(entry, settings) {
|
|
85
|
+
const target = cachePath(entry, settings);
|
|
86
|
+
const cached = await readIfThere(target);
|
|
87
|
+
if (cached !== undefined) {
|
|
88
|
+
if (sha256(cached) === entry.sha256)
|
|
89
|
+
return cached;
|
|
90
|
+
await rm(target, { force: true });
|
|
91
|
+
}
|
|
92
|
+
const url = bundleUrl(entry, settings);
|
|
93
|
+
if (settings.allowNetwork === "none") {
|
|
94
|
+
throw new RenderError("E_STAGE_MISSING", `the TeX bundle ${entry.name} is not in the cache (${target}), and the configuration does not allow the download of ${url}. Set allowNetwork to tex-bundles, or put the file ${entry.file} in the cache folder.`);
|
|
95
|
+
}
|
|
96
|
+
const bytes = await download(url, settings, entry);
|
|
97
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
98
|
+
const temp = `${target}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
99
|
+
await writeFile(temp, bytes);
|
|
100
|
+
try {
|
|
101
|
+
if (bytes.length !== entry.bytes || sha256(bytes) !== entry.sha256) {
|
|
102
|
+
await rm(temp, { force: true });
|
|
103
|
+
throw new RenderError("E_INTEGRITY", `the TeX bundle ${entry.name} from ${url} does not match its pin (sha256 ${entry.sha256}, ${entry.bytes} bytes). The download is deleted.`);
|
|
104
|
+
}
|
|
105
|
+
await rename(temp, target);
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
await rm(temp, { force: true });
|
|
109
|
+
throw e;
|
|
110
|
+
}
|
|
111
|
+
return bytes;
|
|
112
|
+
}
|
|
113
|
+
/** Unpacks an SCTB1 container (see `tools/tex/bundles.mjs`) to a map from the tree name to the file bytes. */
|
|
114
|
+
export function unpackBundle(bytes) {
|
|
115
|
+
const buf = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.length);
|
|
116
|
+
if (buf.length < 8 || buf.toString("latin1", 0, 8) !== MAGIC)
|
|
117
|
+
throw new RenderError("E_INTEGRITY", "a TeX bundle is not an SCTB1 container");
|
|
118
|
+
let body;
|
|
119
|
+
try {
|
|
120
|
+
body = inflateRawSync(buf.subarray(8));
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
throw new RenderError("E_INTEGRITY", `a TeX bundle does not inflate: ${e instanceof Error ? e.message : String(e)}`);
|
|
124
|
+
}
|
|
125
|
+
const out = new Map();
|
|
126
|
+
let at = 4;
|
|
127
|
+
const count = body.readUInt32LE(0);
|
|
128
|
+
for (let i = 0; i < count; i++) {
|
|
129
|
+
const nameLength = body.readUInt16LE(at);
|
|
130
|
+
at += 2;
|
|
131
|
+
const name = body.toString("utf8", at, at + nameLength);
|
|
132
|
+
at += nameLength;
|
|
133
|
+
const size = body.readUInt32LE(at);
|
|
134
|
+
at += 4;
|
|
135
|
+
out.set(name, new Uint8Array(body.buffer, body.byteOffset + at, size));
|
|
136
|
+
at += size;
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
/** The files of the core bundle in this process, by the pinned hash and the loader. A rejected load is not kept. */
|
|
141
|
+
let coreFiles;
|
|
142
|
+
const loadCoreFiles = async (settings) => unpackBundle(await loadBundleBytes(findBundle("core"), settings));
|
|
143
|
+
/**
|
|
144
|
+
* Returns the files of the core bundle. The parent process loads, checks and unpacks the bundle once. Each render
|
|
145
|
+
* worker then gets a copy of the files, so a fresh worker does not read, hash and inflate the bundle again. A load
|
|
146
|
+
* that rejects is not kept, so a later render tries again. `load` is a parameter so that tests replace it.
|
|
147
|
+
*/
|
|
148
|
+
export function texCoreFiles(settings, load = loadCoreFiles) {
|
|
149
|
+
const sha256 = findBundle("core").sha256;
|
|
150
|
+
if (coreFiles?.sha256 === sha256 && coreFiles.load === load)
|
|
151
|
+
return coreFiles.files;
|
|
152
|
+
const files = load(settings);
|
|
153
|
+
coreFiles = { sha256, load, files };
|
|
154
|
+
files.catch(() => {
|
|
155
|
+
if (coreFiles?.files === files)
|
|
156
|
+
coreFiles = undefined;
|
|
157
|
+
});
|
|
158
|
+
return files;
|
|
159
|
+
}
|
|
160
|
+
/** Loads the named bundles and returns the files of each, in the order of the names. A name twice loads once. */
|
|
161
|
+
export async function loadBundles(names, settings, bundles = BUNDLES) {
|
|
162
|
+
const out = new Map();
|
|
163
|
+
for (const name of names) {
|
|
164
|
+
if (out.has(name))
|
|
165
|
+
continue;
|
|
166
|
+
out.set(name, unpackBundle(await loadBundleBytes(findBundle(name, bundles), settings)));
|
|
167
|
+
}
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=bundles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundles.js","sourceRoot":"","sources":["../../src/tex/bundles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,IAAI,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAWxD,kIAAkI;AAClI,MAAM,CAAC,MAAM,OAAO,GAA2B,IAAqB,CAAC;AAcrE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;AAE7C,MAAM,KAAK,GAAG,aAAa,CAAC;AAE5B,MAAM,MAAM,GAAG,CAAC,CAAa,EAAU,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAEvF,yCAAyC;AACzC,MAAM,UAAU,SAAS,CAAC,KAAkB,EAAE,QAA0C;IACtF,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,SAAS,CAAC,KAAkB,EAAE,QAA8C;IAC1F,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC;IACnC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,UAAU,CAAC,IAAgB,EAAE,OAAO,GAA2B,OAAO;IACpF,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACnD,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,WAAW,CAAC,YAAY,EAAE,qCAAqC,IAAI,EAAE,CAAC,CAAC;IAC1G,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qEAAqE;AACrE,KAAK,UAAU,WAAW,CAAC,IAAY;IACrC,IAAI,CAAC;QACH,OAAO,IAAI,UAAU,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAK,CAAuB,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACjE,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,KAAK,UAAU,QAAQ,CAAC,GAAW,EAAE,QAAwB,EAAE,KAAkB;IAC/E,MAAM,IAAI,GAAG,CAAC,GAAW,EAAe,EAAE,CACxC,IAAI,WAAW,CAAC,iBAAiB,EAAE,kBAAkB,KAAK,CAAC,IAAI,wBAAwB,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;IACxG,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CAAC,UAAU,EAAE,8BAA8B,GAAG,uBAAuB,KAAK,CAAC,IAAI,uBAAuB,CAAC,CAAC;IAC/H,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,OAAO,IAAI,UAAU,CAAC,MAAM,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,MAAM,IAAI,CAAC,gBAAgB,MAAM,CAAC,QAAQ,mBAAmB,CAAC,CAAC;IAChI,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACzG,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,CAAC,uBAAuB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9D,IAAI,MAAM,GAAG,KAAK,CAAC,KAAK;YAAE,MAAM,IAAI,WAAW,CAAC,aAAa,EAAE,kBAAkB,KAAK,CAAC,IAAI,SAAS,GAAG,OAAO,MAAM,4BAA4B,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/J,OAAO,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,WAAW;YAAE,MAAM,CAAC,CAAC;QACtC,MAAM,IAAI,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAkB,EAAE,QAAwB;IAChF,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,MAAM;YAAE,OAAO,MAAM,CAAC;QACnD,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACvC,IAAI,QAAQ,CAAC,YAAY,KAAK,MAAM,EAAE,CAAC;QACrC,MAAM,IAAI,WAAW,CACnB,iBAAiB,EACjB,kBAAkB,KAAK,CAAC,IAAI,yBAAyB,MAAM,2DAA2D,GAAG,sDAAsD,KAAK,CAAC,IAAI,uBAAuB,CACjN,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnD,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IAC9E,MAAM,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC;QACH,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;YACnE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAChC,MAAM,IAAI,WAAW,CACnB,aAAa,EACb,kBAAkB,KAAK,CAAC,IAAI,SAAS,GAAG,mCAAmC,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,mCAAmC,CAC3I,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC;IACV,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8GAA8G;AAC9G,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtE,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,KAAK;QAAE,MAAM,IAAI,WAAW,CAAC,aAAa,EAAE,wCAAwC,CAAC,CAAC;IAC7I,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,WAAW,CAAC,aAAa,EAAE,kCAAkC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACvH,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC1C,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACzC,EAAE,IAAI,CAAC,CAAC;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,UAAU,CAAC,CAAC;QACxD,EAAE,IAAI,UAAU,CAAC;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACnC,EAAE,IAAI,CAAC,CAAC;QACR,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QACvE,EAAE,IAAI,IAAI,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,oHAAoH;AACpH,IAAI,SAAyG,CAAC;AAE9G,MAAM,aAAa,GAAG,KAAK,EAAE,QAAwB,EAA4C,EAAE,CACjG,YAAY,CAAC,MAAM,eAAe,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEpE;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAwB,EACxB,IAAI,GAA2E,aAAa;IAE5F,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,SAAS,EAAE,MAAM,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC,KAAK,CAAC;IACpF,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7B,SAAS,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACpC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE;QACf,IAAI,SAAS,EAAE,KAAK,KAAK,KAAK;YAAE,SAAS,GAAG,SAAS,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iHAAiH;AACjH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAA4B,EAC5B,QAAwB,EACxB,OAAO,GAA2B,OAAO;IAEzC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuC,CAAC;IAC3D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5B,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,eAAe,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "core",
|
|
4
|
+
"file": "scieng-tex-core.sctb",
|
|
5
|
+
"sha256": "20b7654bbf6da695eed7eef7895f3a59533f99e675cdb10e48f73d22ac47f43c",
|
|
6
|
+
"bytes": 9383293
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "diagrams",
|
|
10
|
+
"file": "scieng-tex-diagrams.sctb",
|
|
11
|
+
"sha256": "d11be2a1c7931c0d37496852adebe9b3de3deda4bcad98e5396e7eab9c56f2f7",
|
|
12
|
+
"bytes": 71534
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "science",
|
|
16
|
+
"file": "scieng-tex-science.sctb",
|
|
17
|
+
"sha256": "38990ecd718cf5c670c7661418b2a0e427100a8f6b1bb0fc95f21faed0bb45df",
|
|
18
|
+
"bytes": 90196
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "math",
|
|
22
|
+
"file": "scieng-tex-math.sctb",
|
|
23
|
+
"sha256": "ffb760bdb04aa35d4ee56e8bf9ae6a628dd7d204c6aac55d147e651f1854343e",
|
|
24
|
+
"bytes": 721870
|
|
25
|
+
}
|
|
26
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package detection of the TeX stage.
|
|
3
|
+
*
|
|
4
|
+
* The method follows the templater of the Upmath renderer (parpalak/i.upmath.me, MIT licence,
|
|
5
|
+
* copyright Roman Parpalak): the scan looks for known environments and commands in the source
|
|
6
|
+
* and names the package that each one needs. This module adds package lines, TikZ libraries,
|
|
7
|
+
* the comment and verbatim blanking, the bundle tables and the rejection of packages that no
|
|
8
|
+
* bundle holds. It copies no code of the templater.
|
|
9
|
+
*
|
|
10
|
+
* The scan is not a security boundary. TeX runs on a virtual file tree that holds only the
|
|
11
|
+
* bundles, so a package that the scan misses fails inside TeX.
|
|
12
|
+
*/
|
|
13
|
+
/** The name of a TeX bundle. */
|
|
14
|
+
export type BundleName = "core" | "diagrams" | "science" | "math";
|
|
15
|
+
/** The result of a scan. */
|
|
16
|
+
export interface Detection {
|
|
17
|
+
/** The bundles that the source needs, sorted, with `core` first. */
|
|
18
|
+
bundles: BundleName[];
|
|
19
|
+
/** The packages that the source names or implies, sorted, each one once. */
|
|
20
|
+
packages: string[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Scans a TeX source and names the bundles that it needs.
|
|
24
|
+
* Throws E_UNSUPPORTED for a package with the GPL as its only licence, for a package that no bundle holds
|
|
25
|
+
* and for a `fontenc` option other than OT1.
|
|
26
|
+
*/
|
|
27
|
+
export declare function detectBundles(source: string): Detection;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { RenderError } from "../errors.js";
|
|
2
|
+
/** The allowed package names of each bundle. */
|
|
3
|
+
const BUNDLE_PACKAGES = {
|
|
4
|
+
core: [
|
|
5
|
+
"tikz", "pgf", "xcolor", "color", "circuitikz", "standalone", "graphicx", "xkeyval",
|
|
6
|
+
"etoolbox", "ifthen", "array", "calc", "fontenc", "inputenc", "textcomp", "xspace",
|
|
7
|
+
],
|
|
8
|
+
diagrams: ["tikz-cd", "tikz-3dplot", "smartdiagram"],
|
|
9
|
+
science: ["chemfig", "simplekv", "mhchem", "chemgreek", "l3packages", "bussproofs"],
|
|
10
|
+
math: ["amsmath", "amssymb", "amsfonts", "amsthm", "amscd", "amsbsy", "amsopn", "amstext", "amsgen", "eucal"],
|
|
11
|
+
};
|
|
12
|
+
/** The TikZ libraries that a bundle other than core holds. */
|
|
13
|
+
const DIAGRAM_LIBRARIES = ["hobby", "cd"];
|
|
14
|
+
/** The packages with the GPL as their only licence, each with its replacement. */
|
|
15
|
+
const GPL_REPLACEMENTS = {
|
|
16
|
+
pgfplots: "the plotly input type and the plot stage",
|
|
17
|
+
"pgf-umlsd": "a Mermaid sequence diagram",
|
|
18
|
+
xy: "tikz-cd",
|
|
19
|
+
esvect: "\\vec or \\overrightarrow",
|
|
20
|
+
mathrsfs: "\\mathscr from the AMS eucal package",
|
|
21
|
+
};
|
|
22
|
+
/** Environments that need a package. A starred form matches too. */
|
|
23
|
+
const ENVIRONMENT_RULES = [
|
|
24
|
+
["tikzpicture", "tikz"],
|
|
25
|
+
["circuitikz", "circuitikz"],
|
|
26
|
+
["tikzcd", "tikz-cd"],
|
|
27
|
+
["prooftree", "bussproofs"],
|
|
28
|
+
["sequencediagram", "pgf-umlsd"],
|
|
29
|
+
["axis", "pgfplots"],
|
|
30
|
+
["xy", "xy"],
|
|
31
|
+
...[
|
|
32
|
+
"align", "alignat", "flalign", "gather", "multline", "split", "aligned", "gathered", "subequations",
|
|
33
|
+
"cases", "matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "smallmatrix",
|
|
34
|
+
].map((name) => [name, "amsmath"]),
|
|
35
|
+
];
|
|
36
|
+
/** Commands that need a package. A longer command name never matches. */
|
|
37
|
+
const COMMAND_RULES = [
|
|
38
|
+
["tikz", "tikz"],
|
|
39
|
+
["smartdiagram", "smartdiagram"],
|
|
40
|
+
["tdplotsetmaincoords", "tikz-3dplot"],
|
|
41
|
+
["tdplotsetrotatedcoords", "tikz-3dplot"],
|
|
42
|
+
["ce", "mhchem"],
|
|
43
|
+
["chemfig", "chemfig"],
|
|
44
|
+
["addplot", "pgfplots"],
|
|
45
|
+
["xymatrix", "xy"],
|
|
46
|
+
["vv", "esvect"],
|
|
47
|
+
["mathscr", "mathrsfs"],
|
|
48
|
+
...["DisplayProof", "AxiomC", "UnaryInfC", "BinaryInfC", "TrinaryInfC", "QuaternaryInfC", "QuinaryInfC"].map((name) => [name, "bussproofs"]),
|
|
49
|
+
...["color", "textcolor", "colorbox", "pagecolor", "definecolor"].map((name) => [name, "xcolor"]),
|
|
50
|
+
...["mathbb", "mathfrak"].map((name) => [name, "amssymb"]),
|
|
51
|
+
...["text", "dfrac", "tfrac", "binom", "operatorname", "intertext", "substack"].map((name) => [name, "amsmath"]),
|
|
52
|
+
];
|
|
53
|
+
/** Environments whose body the scan blanks. */
|
|
54
|
+
const VERBATIM_BEGIN = /^\\begin\s*\{(verbatim\*?|lstlisting|minted)\}/;
|
|
55
|
+
const VERB = /^\\verb\*?([^A-Za-z\s*])/;
|
|
56
|
+
const PACKAGE_LINE = /\\(?:usepackage|RequirePackage(?:WithOptions)?)\s*(?:\[([^\]]*)\])?\s*\{([^}]*)\}/g;
|
|
57
|
+
const LIBRARY_LINE = /\\usetikzlibrary\s*\{([^}]*)\}/g;
|
|
58
|
+
const BUNDLE_OF = new Map();
|
|
59
|
+
for (const [bundle, names] of Object.entries(BUNDLE_PACKAGES)) {
|
|
60
|
+
for (const name of names) {
|
|
61
|
+
BUNDLE_OF.set(name, bundle);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** The only font encoding that the bundles hold. Latin Modern, which T1 and the other encodings need, is in no bundle. */
|
|
65
|
+
const BUNDLED_ENCODING = "OT1";
|
|
66
|
+
/** The first option of a `fontenc` line that names an encoding other than OT1, or `undefined`. */
|
|
67
|
+
function foreignEncoding(options) {
|
|
68
|
+
return (options ?? "")
|
|
69
|
+
.split(",")
|
|
70
|
+
.map((option) => option.trim())
|
|
71
|
+
.find((option) => option !== "" && option !== BUNDLED_ENCODING);
|
|
72
|
+
}
|
|
73
|
+
/** Replaces the characters of a range with spaces and keeps the line breaks. */
|
|
74
|
+
function blank(chars, from, to) {
|
|
75
|
+
for (let k = from; k < to; k += 1) {
|
|
76
|
+
if (chars[k] !== "\n") {
|
|
77
|
+
chars[k] = " ";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Blanks the comments, the verbatim bodies, the `\verb` text and each double backslash.
|
|
83
|
+
* The result has the length of the source and the same line breaks.
|
|
84
|
+
*/
|
|
85
|
+
function sanitize(source) {
|
|
86
|
+
const chars = source.split("");
|
|
87
|
+
let i = 0;
|
|
88
|
+
while (i < source.length) {
|
|
89
|
+
const c = source[i];
|
|
90
|
+
if (c === "%") {
|
|
91
|
+
const end = source.indexOf("\n", i);
|
|
92
|
+
const stop = end < 0 ? source.length : end;
|
|
93
|
+
blank(chars, i, stop);
|
|
94
|
+
i = stop;
|
|
95
|
+
}
|
|
96
|
+
else if (c === "\\") {
|
|
97
|
+
const rest = source.slice(i, i + 40);
|
|
98
|
+
const begin = VERBATIM_BEGIN.exec(rest);
|
|
99
|
+
const verb = VERB.exec(rest);
|
|
100
|
+
const next = source[i + 1];
|
|
101
|
+
if (begin !== null) {
|
|
102
|
+
const bodyStart = i + begin[0].length;
|
|
103
|
+
const end = source.indexOf(`\\end{${begin[1]}}`, bodyStart);
|
|
104
|
+
if (end >= 0) {
|
|
105
|
+
blank(chars, bodyStart, end);
|
|
106
|
+
i = end;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
i = bodyStart;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (verb !== null) {
|
|
113
|
+
const textStart = i + verb[0].length;
|
|
114
|
+
const close = source.indexOf(verb[1], textStart);
|
|
115
|
+
const lineEnd = source.indexOf("\n", textStart);
|
|
116
|
+
if (close >= 0 && (lineEnd < 0 || close < lineEnd)) {
|
|
117
|
+
blank(chars, i, close + 1);
|
|
118
|
+
i = close + 1;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
i += verb[0].length;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else if (next === "\\") {
|
|
125
|
+
blank(chars, i, i + 2);
|
|
126
|
+
i += 2;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
i += 2;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
i += 1;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return chars.join("");
|
|
137
|
+
}
|
|
138
|
+
/** Collects the first position of each package that the clean text names or implies. */
|
|
139
|
+
function findPackages(text) {
|
|
140
|
+
const findings = [];
|
|
141
|
+
const extra = new Set();
|
|
142
|
+
for (const m of text.matchAll(PACKAGE_LINE)) {
|
|
143
|
+
for (const part of m[2].split(",")) {
|
|
144
|
+
const name = part.trim();
|
|
145
|
+
if (name !== "") {
|
|
146
|
+
const encoding = name === "fontenc" ? foreignEncoding(m[1]) : undefined;
|
|
147
|
+
findings.push(encoding === undefined ? { name, index: m.index } : { name, index: m.index, encoding });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
for (const m of text.matchAll(LIBRARY_LINE)) {
|
|
152
|
+
for (const part of m[1].split(",")) {
|
|
153
|
+
if (DIAGRAM_LIBRARIES.includes(part.trim())) {
|
|
154
|
+
extra.add("diagrams");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
for (const [env, name] of ENVIRONMENT_RULES) {
|
|
159
|
+
const hit = new RegExp(`\\\\begin\\s*\\{${env}\\*?\\}`).exec(text);
|
|
160
|
+
if (hit !== null) {
|
|
161
|
+
findings.push({ name, index: hit.index });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const [command, name] of COMMAND_RULES) {
|
|
165
|
+
const hit = new RegExp(`\\\\${command}(?![A-Za-z])`).exec(text);
|
|
166
|
+
if (hit !== null) {
|
|
167
|
+
findings.push({ name, index: hit.index });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { findings, extra };
|
|
171
|
+
}
|
|
172
|
+
function lineOf(text, index) {
|
|
173
|
+
let line = 1;
|
|
174
|
+
for (let k = 0; k < index; k += 1) {
|
|
175
|
+
if (text[k] === "\n") {
|
|
176
|
+
line += 1;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return line;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Scans a TeX source and names the bundles that it needs.
|
|
183
|
+
* Throws E_UNSUPPORTED for a package with the GPL as its only licence, for a package that no bundle holds
|
|
184
|
+
* and for a `fontenc` option other than OT1.
|
|
185
|
+
*/
|
|
186
|
+
export function detectBundles(source) {
|
|
187
|
+
const text = sanitize(source);
|
|
188
|
+
const { findings, extra } = findPackages(text);
|
|
189
|
+
findings.sort((a, b) => a.index - b.index);
|
|
190
|
+
const bundles = new Set(["core", ...extra]);
|
|
191
|
+
const packages = new Set();
|
|
192
|
+
for (const { name, index, encoding } of findings) {
|
|
193
|
+
if (encoding !== undefined) {
|
|
194
|
+
throw new RenderError("E_UNSUPPORTED", `Font encoding "${encoding}" is not available: only the OT1 encoding is bundled, and the Latin Modern fonts that T1 needs are in no bundle. Use the OT1 encoding or remove the fontenc option.`, { line: lineOf(text, index) });
|
|
195
|
+
}
|
|
196
|
+
const replacement = Object.hasOwn(GPL_REPLACEMENTS, name) ? GPL_REPLACEMENTS[name] : undefined;
|
|
197
|
+
const bundle = BUNDLE_OF.get(name);
|
|
198
|
+
if (replacement !== undefined) {
|
|
199
|
+
throw new RenderError("E_UNSUPPORTED", `TeX package "${name}" has the GPL as its only licence, so no bundle holds it. Replacement: ${replacement}.`, { line: lineOf(text, index) });
|
|
200
|
+
}
|
|
201
|
+
if (bundle === undefined) {
|
|
202
|
+
throw new RenderError("E_UNSUPPORTED", `TeX package "${name}" is not in any bundle.`, {
|
|
203
|
+
line: lineOf(text, index),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
bundles.add(bundle);
|
|
207
|
+
packages.add(name);
|
|
208
|
+
}
|
|
209
|
+
const rest = [...bundles].filter((b) => b !== "core").sort();
|
|
210
|
+
return { bundles: ["core", ...rest], packages: [...packages].sort() };
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/tex/detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { SpecialPosition, SpecialResult } from "./specials.ts";
|
|
2
|
+
/** The files of one font: the TFM, and the PFB when the font has outlines. */
|
|
3
|
+
export interface FontFiles {
|
|
4
|
+
tfm: Uint8Array;
|
|
5
|
+
pfb: Uint8Array | null;
|
|
6
|
+
}
|
|
7
|
+
/** The options of the DVI converter. */
|
|
8
|
+
export interface DviOptions {
|
|
9
|
+
/** The page to draw, counted from 1. The default is 1. */
|
|
10
|
+
page?: number;
|
|
11
|
+
/** The border around the marks, in SVG units. The default is 1. */
|
|
12
|
+
margin?: number;
|
|
13
|
+
/** The size of one TeX point in SVG units. The default is 1. */
|
|
14
|
+
unitPerPt?: number;
|
|
15
|
+
/** Reads one `\special` at the current position. It can give SVG text for the page and a box for the bounds. */
|
|
16
|
+
special?: (text: string, at: SpecialPosition) => SpecialResult | null;
|
|
17
|
+
/**
|
|
18
|
+
* Tells whether the page is inside a transformed group. While it gives true, the boxes of glyphs and rules do not
|
|
19
|
+
* join the bounds, because their DVI positions are not their places on the page. The boxes of specials still do.
|
|
20
|
+
*/
|
|
21
|
+
transformed?: () => boolean;
|
|
22
|
+
}
|
|
23
|
+
/** The result of the DVI converter. */
|
|
24
|
+
export interface DviSvg {
|
|
25
|
+
svg: string;
|
|
26
|
+
/** The number of glyph paths on the drawn page. */
|
|
27
|
+
glyphs: number;
|
|
28
|
+
/** The number of rules on the drawn page. */
|
|
29
|
+
rules: number;
|
|
30
|
+
/** The number of `\special` commands in the file. */
|
|
31
|
+
specials: number;
|
|
32
|
+
/** The number of pages in the file. */
|
|
33
|
+
pages: number;
|
|
34
|
+
/** The fonts and glyphs (`font:code`) that have no file or no outline. */
|
|
35
|
+
missing: string[];
|
|
36
|
+
/** The fonts that the file names, by font name. */
|
|
37
|
+
fonts: string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Converts a DVI file to SVG.
|
|
41
|
+
* `fontFiles` gives the files of a font by name. It returns `null` for an unknown font.
|
|
42
|
+
* A font with no PFB keeps its TFM advances, and each of its glyphs goes in the missing list.
|
|
43
|
+
*/
|
|
44
|
+
export declare function dviToSvg(dvi: Uint8Array, fontFiles: (name: string) => FontFiles | null, opt?: DviOptions): DviSvg;
|