@lofcz/tikz 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/LICENSE +674 -0
  2. package/NOTICE.md +30 -0
  3. package/README.md +127 -2
  4. package/package.json +56 -4
  5. package/runtime/LICENSE +165 -0
  6. package/runtime/NOTICE.md +32 -0
  7. package/runtime/dist/auto.d.ts +68 -0
  8. package/runtime/dist/auto.js +564 -0
  9. package/runtime/dist/bibtex.mjs +2 -0
  10. package/runtime/dist/bibtex.wasm +0 -0
  11. package/runtime/dist/bundles/cm-tfm/files.br +0 -0
  12. package/runtime/dist/bundles/cm-tfm/files.index.json +1 -0
  13. package/runtime/dist/bundles/cm-tfm/manifest.json +1 -0
  14. package/runtime/dist/bundles/cm-type1/files.br +0 -0
  15. package/runtime/dist/bundles/cm-type1/files.index.json +1 -0
  16. package/runtime/dist/bundles/cm-type1/manifest.json +1 -0
  17. package/runtime/dist/bundles/core/files.br +0 -0
  18. package/runtime/dist/bundles/core/files.index.json +1 -0
  19. package/runtime/dist/bundles/core/manifest.json +1 -0
  20. package/runtime/dist/bundles/hot.json +1 -0
  21. package/runtime/dist/bundles/index.json +80 -0
  22. package/runtime/dist/bundles/latex-core/files.br +0 -0
  23. package/runtime/dist/bundles/latex-core/files.index.json +1 -0
  24. package/runtime/dist/bundles/latex-core/manifest.json +1 -0
  25. package/runtime/dist/bundles/latex-extra/files.br +0 -0
  26. package/runtime/dist/bundles/latex-extra/files.index.json +1 -0
  27. package/runtime/dist/bundles/latex-extra/manifest.json +1 -0
  28. package/runtime/dist/bundles/lm-fonts/files.br +0 -0
  29. package/runtime/dist/bundles/lm-fonts/files.index.json +1 -0
  30. package/runtime/dist/bundles/lm-fonts/manifest.json +1 -0
  31. package/runtime/dist/bundles/luatex/files.br +0 -0
  32. package/runtime/dist/bundles/luatex/files.index.json +1 -0
  33. package/runtime/dist/bundles/luatex/manifest.json +1 -0
  34. package/runtime/dist/bundles/ps-fonts/files.br +0 -0
  35. package/runtime/dist/bundles/ps-fonts/files.index.json +1 -0
  36. package/runtime/dist/bundles/ps-fonts/manifest.json +1 -0
  37. package/runtime/dist/bundles/tex-plain/files.br +0 -0
  38. package/runtime/dist/bundles/tex-plain/files.index.json +1 -0
  39. package/runtime/dist/bundles/tex-plain/manifest.json +1 -0
  40. package/runtime/dist/bundles/tikz-snapshot/files.br +0 -0
  41. package/runtime/dist/bundles/tikz-snapshot/files.index.json +1 -0
  42. package/runtime/dist/bundles/tikz-snapshot/manifest.json +1 -0
  43. package/runtime/dist/bundles-config.d.ts +3 -0
  44. package/runtime/dist/bundles-config.js +16 -0
  45. package/runtime/dist/cli.d.ts +2 -0
  46. package/runtime/dist/cli.js +372 -0
  47. package/runtime/dist/core.d.ts +124 -0
  48. package/runtime/dist/core.js +927 -0
  49. package/runtime/dist/diagnostics.d.ts +53 -0
  50. package/runtime/dist/diagnostics.js +184 -0
  51. package/runtime/dist/dvisvgm.d.ts +20 -0
  52. package/runtime/dist/dvisvgm.js +46 -0
  53. package/runtime/dist/dvisvgm.mjs +2 -0
  54. package/runtime/dist/dvisvgm.wasm +0 -0
  55. package/runtime/dist/figures.d.ts +92 -0
  56. package/runtime/dist/figures.js +250 -0
  57. package/runtime/dist/ghostscript.d.ts +92 -0
  58. package/runtime/dist/ghostscript.js +218 -0
  59. package/runtime/dist/index.d.ts +87 -0
  60. package/runtime/dist/index.js +364 -0
  61. package/runtime/dist/logger.d.ts +48 -0
  62. package/runtime/dist/logger.js +55 -0
  63. package/runtime/dist/luatex.mjs +2 -0
  64. package/runtime/dist/luatex.wasm +0 -0
  65. package/runtime/dist/makeindex.mjs +2 -0
  66. package/runtime/dist/makeindex.wasm +0 -0
  67. package/runtime/dist/mplib.d.ts +106 -0
  68. package/runtime/dist/mplib.js +85 -0
  69. package/runtime/dist/mplib.mjs +2 -0
  70. package/runtime/dist/mplib.wasm +0 -0
  71. package/runtime/dist/node.d.ts +4 -0
  72. package/runtime/dist/node.js +49 -0
  73. package/runtime/dist/postscript.d.ts +21 -0
  74. package/runtime/dist/postscript.js +130 -0
  75. package/runtime/dist/prerender.d.ts +55 -0
  76. package/runtime/dist/prerender.js +106 -0
  77. package/runtime/dist/render/svg.d.ts +20 -0
  78. package/runtime/dist/render/svg.js +96 -0
  79. package/runtime/dist/tex/bridge.d.ts +93 -0
  80. package/runtime/dist/tex/bridge.js +223 -0
  81. package/runtime/dist/tex/cache-key.d.ts +33 -0
  82. package/runtime/dist/tex/cache-key.js +150 -0
  83. package/runtime/dist/tex/mpto.d.ts +60 -0
  84. package/runtime/dist/tex/mpto.js +112 -0
  85. package/runtime/dist/tex/mpx.d.ts +25 -0
  86. package/runtime/dist/tex/mpx.js +54 -0
  87. package/runtime/dist/tex/scanner.d.ts +78 -0
  88. package/runtime/dist/tex/scanner.js +326 -0
  89. package/runtime/dist/tex.mjs +2 -0
  90. package/runtime/dist/tex.wasm +0 -0
  91. package/runtime/dist/texengine.d.ts +35 -0
  92. package/runtime/dist/texengine.js +57 -0
  93. package/runtime/dist/texutils.d.ts +19 -0
  94. package/runtime/dist/texutils.js +60 -0
  95. package/runtime/dist/types.d.ts +376 -0
  96. package/runtime/dist/types.js +6 -0
  97. package/runtime/dist/vfs/bundle.d.ts +88 -0
  98. package/runtime/dist/vfs/bundle.js +315 -0
  99. package/runtime/dist/vfs/lazyfs.d.ts +62 -0
  100. package/runtime/dist/vfs/lazyfs.js +133 -0
  101. package/runtime/dist/worker.d.ts +15 -0
  102. package/runtime/dist/worker.js +143 -0
  103. package/runtime/licenses/COPYING.AFPL +230 -0
  104. package/runtime/licenses/COPYING.makeindex +42 -0
  105. package/runtime/licenses/GPL-3.0.txt +674 -0
  106. package/runtime/licenses/LGPL-3.0.txt +165 -0
  107. package/runtime/licenses/OFL-1.1.txt +93 -0
  108. package/runtime/package.json +1 -0
  109. package/runtime/upstream.json +27 -0
  110. package/src/browser-worker.js +26 -0
  111. package/src/browser.d.ts +18 -0
  112. package/src/browser.js +68 -0
  113. package/src/deploy.d.ts +5 -0
  114. package/src/deploy.js +48 -0
  115. package/src/index.d.ts +28 -0
  116. package/src/index.js +103 -0
  117. package/src/worker.js +15 -0
  118. package/upstream.json +27 -0
@@ -0,0 +1,372 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * mpost-wasm — a drop-in for `mpost` for the common flag set (docs/08 §5).
4
+ *
5
+ * mpost-wasm [OPTION]... [MPNAME[.mp]] [COMMANDS]
6
+ * mpost-wasm --dvitomp DVINAME[.dvi] [MPXNAME[.mpx]]
7
+ * mpost-wasm --prerender [--figures=DIR | --base=DIR] [--force] [--dry-run] PAGE.html...
8
+ */
9
+ import { MetaPost, LOG_LEVELS, DEFAULT_BUNDLES } from './index.js';
10
+ import { prerender } from './prerender.js';
11
+ const HELP = `Usage: mpost-wasm [OPTION]... [MPNAME[.mp]] [COMMANDS]
12
+ mpost-wasm --latex [OPTION]... DOC.tex
13
+ mpost-wasm --prerender [--figures=DIR | --base=DIR] [--force] [--dry-run] PAGE.html...
14
+ Run MetaPost (WebAssembly build) on MPNAME, writing output files to the
15
+ current directory like mpost does; or, with --latex, typeset a complete
16
+ LaTeX/TikZ (or plain TeX, with --plain) document with tex.wasm and convert
17
+ every page to DOC-<page>.svg with dvisvgm.wasm.
18
+
19
+ -interaction=MODE batchmode|nonstopmode|scrollmode (default nonstopmode)
20
+ -numbersystem=SYSTEM scaled|double|decimal (binary/interval are not built)
21
+ -jobname=STRING output name (default: basename of MPNAME)
22
+ -tex=PROGRAM tex|etex|latex|auto (default auto)
23
+ -s INTERNAL=VALUE set an internal, e.g. -s prologues=3 -s outputformat="svg"
24
+ -halt-on-error stop at the first error
25
+ -file-line-error (accepted; diagnostics always carry file:line)
26
+ -recorder write a .fls file listing every file opened
27
+ -T, -troff accepted; troff mode is unsupported and warns
28
+ --format=eps|svg|json output format (default eps; or set outputformat)
29
+ --texmf=DIR use a texmf directory (flattened layout) instead of bundles
30
+ --bundles=DIR directory containing the bundles (default: next to this package)
31
+ --stdout print the first figure to stdout instead of writing files
32
+ --latex DOC.tex -> DOC-1.svg, DOC-2.svg ... (LaTeX); --plain for plain TeX
33
+ --engine=NAME latex | lualatex | luatex | plain | tex | auto (default auto: lualatex when
34
+ the document uses graphdrawing or \directlua)
35
+ --fonts=paths|woff2 how text is emitted in --latex mode (default paths)
36
+ --pdf with --latex: write DOC.pdf (pdfTeX's or LuaTeX's own PDF output)
37
+ instead of SVG pages; with --stdout, the PDF goes to stdout
38
+ --opentype load the OpenType bundles so \\usepackage{fontspec} works under
39
+ --engine=lualatex; off by default because LaTeX initialises
40
+ luaotfload on every LuaTeX run once it can find it
41
+ --prerender typeset the <script type="text/tikz|metapost">, <tikz-diagram> and
42
+ <metapost-diagram> elements of each PAGE and save each as figure-HASH.svg in
43
+ the directory the page's auto.js loader names in data-figures (default
44
+ figures/, next to the page); the tags then load the files instead of running
45
+ the engines. Files that exist are kept: the name is the content.
46
+ --figures=DIR save every page's figures in DIR instead
47
+ --base=DIR resolve each page's data-figures against DIR instead of the page's own
48
+ directory (for a rendered copy of a page saved elsewhere)
49
+ --force re-render figures whose file exists
50
+ --dry-run list what would be rendered, render nothing
51
+ -v, -vv, -vvv more on stderr: timings; the engines' output as it runs; every file
52
+ -q, --quiet nothing on stderr (not even TeX errors)
53
+ --log-level=LEVEL silent|error|warn|info|debug|trace (default warn)
54
+ -help, -version
55
+ `;
56
+ function parseArgs(argv) {
57
+ const o = {
58
+ interaction: 'nonstop',
59
+ numbersystem: 'scaled',
60
+ jobname: '', tex: 'auto', internals: {},
61
+ halt: false, recorder: false, troff: false, format: '', texmf: '', bundles: '', opentype: false,
62
+ stdout: false, file: '', commands: '', help: false, version: false, dvitomp: false,
63
+ latex: false, plain: false, pdf: false, engine: 'auto', fonts: 'paths',
64
+ verbose: 0, quiet: false, logLevel: '',
65
+ prerender: false, figures: '', base: '', force: false, dryRun: false, args: [],
66
+ };
67
+ const rest = [];
68
+ for (let i = 0; i < argv.length; i++) {
69
+ const a = argv[i];
70
+ const next = () => argv[++i];
71
+ const kv = (a.startsWith('--') ? a.slice(2) : a.slice(1));
72
+ const [k, v] = kv.includes('=') ? [kv.slice(0, kv.indexOf('=')), kv.slice(kv.indexOf('=') + 1)] : [kv, undefined];
73
+ if (!a.startsWith('-') || a === '-') {
74
+ rest.push(a);
75
+ continue;
76
+ }
77
+ switch (k) {
78
+ case 'interaction':
79
+ o.interaction = (v ?? next()).replace('mode', '');
80
+ break;
81
+ case 'numbersystem':
82
+ o.numbersystem = (v ?? next());
83
+ break;
84
+ case 'jobname':
85
+ o.jobname = v ?? next();
86
+ break;
87
+ case 'tex': {
88
+ const t = v ?? next();
89
+ o.tex = t === 'tex' ? 'plain' : t;
90
+ break;
91
+ }
92
+ case 's': {
93
+ const s = v ?? next();
94
+ const eq = s.indexOf('=');
95
+ const name = s.slice(0, eq);
96
+ let val = s.slice(eq + 1);
97
+ if (/^".*"$/.test(val))
98
+ val = val.slice(1, -1);
99
+ else if (!isNaN(Number(val)))
100
+ val = Number(val);
101
+ o.internals[name] = val;
102
+ break;
103
+ }
104
+ case 'halt-on-error':
105
+ o.halt = true;
106
+ break;
107
+ case 'file-line-error':
108
+ case 'file-line-error-style': break;
109
+ case 'no-file-line-error': break;
110
+ case 'recorder':
111
+ o.recorder = true;
112
+ break;
113
+ case 'T':
114
+ case 'troff':
115
+ o.troff = true;
116
+ break;
117
+ case 'format':
118
+ o.format = (v ?? next());
119
+ break;
120
+ case 'texmf':
121
+ o.texmf = v ?? next();
122
+ break;
123
+ case 'bundles':
124
+ o.bundles = v ?? next();
125
+ break;
126
+ case 'opentype':
127
+ o.opentype = true;
128
+ break;
129
+ case 'stdout':
130
+ o.stdout = true;
131
+ break;
132
+ case 'pdf':
133
+ o.pdf = true;
134
+ break;
135
+ case 'help':
136
+ o.help = true;
137
+ break;
138
+ case 'version':
139
+ o.version = true;
140
+ break;
141
+ case 'dvitomp':
142
+ o.dvitomp = true;
143
+ break;
144
+ case 'latex':
145
+ o.latex = true;
146
+ break;
147
+ case 'plain':
148
+ o.plain = true;
149
+ o.latex = true;
150
+ o.engine = 'plain';
151
+ break;
152
+ case 'engine':
153
+ o.engine = (v ?? next());
154
+ o.latex = true;
155
+ break;
156
+ case 'fonts':
157
+ o.fonts = (v ?? next());
158
+ break;
159
+ case 'prerender':
160
+ o.prerender = true;
161
+ break;
162
+ case 'figures':
163
+ o.figures = v ?? next();
164
+ break;
165
+ case 'base':
166
+ o.base = v ?? next();
167
+ break;
168
+ case 'force':
169
+ o.force = true;
170
+ break;
171
+ case 'dry-run':
172
+ o.dryRun = true;
173
+ break;
174
+ case 'v':
175
+ case 'verbose':
176
+ o.verbose++;
177
+ break;
178
+ case 'vv':
179
+ o.verbose += 2;
180
+ break;
181
+ case 'vvv':
182
+ o.verbose += 3;
183
+ break;
184
+ case 'q':
185
+ case 'quiet':
186
+ o.quiet = true;
187
+ break;
188
+ case 'log-level':
189
+ o.logLevel = (v ?? next());
190
+ break;
191
+ case 'ini':
192
+ case 'mem':
193
+ case 'progname':
194
+ case 'kpathsea-debug':
195
+ case 'restricted':
196
+ case 'debug':
197
+ case 'translate-file':
198
+ case '8bit':
199
+ console.error(`mpost-wasm: warning: option -${k} is accepted and ignored`);
200
+ if (v === undefined && ['mem', 'progname', 'kpathsea-debug', 'translate-file'].includes(k))
201
+ next();
202
+ break;
203
+ default:
204
+ console.error(`mpost-wasm: unknown option ${a}`);
205
+ process.exit(1);
206
+ }
207
+ }
208
+ o.args = [...rest];
209
+ if (rest.length) {
210
+ const first = rest[0];
211
+ if (first.startsWith('&')) {
212
+ rest.shift();
213
+ }
214
+ }
215
+ if (rest.length) {
216
+ o.file = rest.shift();
217
+ }
218
+ o.commands = rest.join(' ');
219
+ return o;
220
+ }
221
+ async function main() {
222
+ const fs = await import('node:fs');
223
+ const path = await import('node:path');
224
+ const o = parseArgs(process.argv.slice(2));
225
+ if (o.help) {
226
+ process.stdout.write(HELP);
227
+ return;
228
+ }
229
+ const logLevel = o.logLevel || (o.quiet ? 'silent' : o.verbose >= 3 ? 'trace' : o.verbose === 2 ? 'debug' : o.verbose === 1 ? 'info' : 'warn');
230
+ if (!LOG_LEVELS.includes(logLevel)) {
231
+ console.error(`mpost-wasm: unknown log level ${logLevel} (${LOG_LEVELS.join(', ')})`);
232
+ process.exit(1);
233
+ }
234
+ // Everything the level admits goes to stderr, so stdout stays the transcript (and, with --stdout, the figure).
235
+ // MetaPost's own errors and warnings are left out: the transcript on stdout carries them, as with mpost.
236
+ const logger = (r) => {
237
+ if (!o.prerender && r.source === 'metapost' && (r.level === 'error' || r.level === 'warn'))
238
+ return;
239
+ const raw = (r.level === 'debug' || r.level === 'trace') && r.source !== 'host';
240
+ process.stderr.write(raw ? `${r.source}: ${r.message}\n` : `mpost-wasm: ${r.source === 'host' ? '' : r.source + ': '}${r.message}\n`);
241
+ };
242
+ if (o.prerender) {
243
+ // the browser's defaults (deterministic, seed 42), so the files are the bytes the tags would produce
244
+ const pages = o.args.filter((a) => !a.startsWith('&'));
245
+ if (!pages.length) {
246
+ console.error('mpost-wasm: --prerender needs one or more .html pages');
247
+ process.exit(1);
248
+ }
249
+ for (const p of pages)
250
+ if (!fs.existsSync(p)) {
251
+ console.error(`mpost-wasm: cannot open ${p}`);
252
+ process.exit(1);
253
+ }
254
+ // each page's own data-bundles decide its engine's bundles, as in the browser; --opentype adds to them
255
+ const r = await prerender(pages, {
256
+ createOptions: { texmfDir: o.texmf || undefined, bundleBaseUrl: o.bundles ? 'file://' + path.resolve(o.bundles) + '/' : undefined, logLevel, logger },
257
+ addBundles: o.opentype ? ['opentype', 'otf-fonts'] : undefined,
258
+ figuresDir: o.figures ? path.resolve(o.figures) : undefined, baseDir: o.base ? path.resolve(o.base) : undefined,
259
+ force: o.force, dryRun: o.dryRun, report: (l) => process.stdout.write(l + '\n'),
260
+ });
261
+ const pending = r.entries.filter((e) => e.status === 'pending').length;
262
+ process.stdout.write(`mpost-wasm: ${r.rendered} rendered, ${r.existing} already saved, ${r.failed} failed${o.dryRun ? `, ${pending} to render` : ''}\n`);
263
+ process.exit(r.failed ? 1 : 0);
264
+ }
265
+ const mp = await MetaPost.create({
266
+ numberSystem: o.numbersystem, tex: o.tex, interaction: o.interaction, haltOnError: o.halt,
267
+ texmfDir: o.texmf || undefined, bundleBaseUrl: o.bundles ? 'file://' + path.resolve(o.bundles) + '/' : undefined,
268
+ bundles: o.opentype ? [...DEFAULT_BUNDLES, 'opentype', 'otf-fonts'] : undefined,
269
+ deterministic: false, logLevel, logger,
270
+ });
271
+ if (o.version) {
272
+ console.log(`MetaPost ${mp.version.metapost} (mp-tikz-wasm) with ${mp.version.tex}`);
273
+ mp.dispose();
274
+ return;
275
+ }
276
+ if (o.troff)
277
+ console.error('mpost-wasm: warning: troff mode is not supported; continuing in TeX mode');
278
+ if (o.latex) {
279
+ if (!o.file) {
280
+ console.error('mpost-wasm: --latex needs a .tex file');
281
+ process.exit(1);
282
+ }
283
+ const f = fs.existsSync(o.file) ? o.file : fs.existsSync(o.file + '.tex') ? o.file + '.tex' : null;
284
+ if (!f) {
285
+ console.error(`mpost-wasm: cannot open ${o.file}`);
286
+ process.exit(1);
287
+ }
288
+ const job = o.jobname || path.basename(f).replace(/\.tex$/, '');
289
+ const sib = {};
290
+ // sibling inputs; PNG and JPEG too, which pdfTeX and LuaTeX include in PDF output
291
+ for (const e of fs.readdirSync(path.dirname(f)))
292
+ if (e !== path.basename(f) && /\.(tex|sty|cls|def|clo|fd|eps|dat|csv|txt|bib|png|jpe?g)$/i.test(e))
293
+ sib[e] = fs.readFileSync(path.join(path.dirname(f), e));
294
+ const r = await mp.latex(fs.readFileSync(f, 'utf8'), { engine: o.engine, jobName: job, files: sib, fonts: o.fonts, output: o.pdf ? 'pdf' : 'svg' });
295
+ // with --pdf --stdout, stdout is the PDF alone: the transcript goes to stderr instead
296
+ (o.pdf && o.stdout ? process.stderr : process.stdout).write(r.log.endsWith('\n') ? r.log : r.log + '\n');
297
+ if (o.pdf) {
298
+ if (r.pdf) {
299
+ if (o.stdout)
300
+ process.stdout.write(r.pdf);
301
+ else
302
+ fs.writeFileSync(`${job}.pdf`, r.pdf);
303
+ }
304
+ }
305
+ else if (o.stdout) {
306
+ if (r.pages[0])
307
+ process.stdout.write(r.pages[0]);
308
+ }
309
+ else
310
+ r.pages.forEach((svg, i) => fs.writeFileSync(`${job}-${i + 1}.svg`, svg));
311
+ fs.writeFileSync(`${job}.log`, r.texLog);
312
+ mp.dispose();
313
+ process.exit(r.status === 'error' || r.status === 'fatal' ? 1 : 0);
314
+ }
315
+ let source;
316
+ let jobname = o.jobname;
317
+ let files = {};
318
+ if (o.file) {
319
+ const f = fs.existsSync(o.file) ? o.file : fs.existsSync(o.file + '.mp') ? o.file + '.mp' : null;
320
+ if (!f) {
321
+ console.error(`mpost-wasm: cannot open ${o.file}`);
322
+ process.exit(1);
323
+ }
324
+ source = fs.readFileSync(f, 'utf8');
325
+ if (!jobname)
326
+ jobname = path.basename(f).replace(/\.mp$/, '');
327
+ // make sibling .mp files inputtable
328
+ for (const e of fs.readdirSync(path.dirname(f)))
329
+ if (/\.(mp|tex|dat|txt)$/.test(e) && e !== path.basename(f))
330
+ files[e] = fs.readFileSync(path.join(path.dirname(f), e));
331
+ if (o.commands)
332
+ source += '\n' + o.commands;
333
+ }
334
+ else if (o.commands) {
335
+ source = o.commands;
336
+ if (!jobname)
337
+ jobname = 'mpout';
338
+ }
339
+ else {
340
+ source = fs.readFileSync(0, 'utf8');
341
+ if (!jobname)
342
+ jobname = 'mpout';
343
+ }
344
+ const internals = { ...o.internals };
345
+ let format = o.format || 'eps';
346
+ if (!o.format && typeof internals.outputformat === 'string')
347
+ format = internals.outputformat === 'svg' ? 'svg' : 'eps';
348
+ const prologues = typeof internals.prologues === 'number' ? internals.prologues : format === 'svg' ? 3 : 0;
349
+ const r = await mp.run(source, { jobName: jobname, files, internals, format, prologues, svg: { precision: false, idPrefix: false } });
350
+ process.stdout.write(r.log.endsWith('\n') ? r.log : r.log + '\n'); // MetaPost's terminal transcript, like mpost
351
+ // like mpost: the default outputtemplate is %j.%c whatever the format; %o expands to the format's extension
352
+ const ext = format === 'svg' ? 'svg' : format === 'json' ? 'json' : 'eps';
353
+ const template = typeof internals.outputtemplate === 'string' ? internals.outputtemplate : `%j.%c`;
354
+ for (const fig of r.figures) {
355
+ const name = template.replace('%j', jobname).replace('%c', String(fig.charcode)).replace('%o', ext);
356
+ const body = format === 'svg' ? fig.svg : format === 'json' ? JSON.stringify(fig.json) : fig.eps;
357
+ if (o.stdout) {
358
+ process.stdout.write(body);
359
+ break;
360
+ }
361
+ fs.writeFileSync(name, body);
362
+ }
363
+ for (const [name, data] of Object.entries(r.artifacts))
364
+ if (name !== `${jobname}.log` || true)
365
+ fs.writeFileSync(name, data);
366
+ if (o.recorder)
367
+ fs.writeFileSync(`${jobname}.fls`, r.diagnostics.map(() => '').join(''));
368
+ mp.dispose();
369
+ process.exit(r.history >= 2 ? 1 : 0);
370
+ }
371
+ main().catch((e) => { console.error(e?.stack ?? String(e)); process.exit(2); });
372
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,124 @@
1
+ /**
2
+ * core.ts — the orchestrator (docs/01 §3). Runs in a Worker (browser) or on
3
+ * the main thread (Node). Owns one mplib.wasm instance for its lifetime and
4
+ * creates one tex.wasm instance per TeX invocation.
5
+ */
6
+ import { type MplibModule, type MplibFactory } from './mplib.js';
7
+ import { type TexFactory } from './texengine.js';
8
+ import { type DvisvgmFactory } from './dvisvgm.js';
9
+ import type { Ghostscript } from './ghostscript.js';
10
+ import { BundleSet } from './vfs/bundle.js';
11
+ import { Logger } from './logger.js';
12
+ import type { MetaPostOptions, RunOptions, RunResult, Diagnostic, ProgressEvent, LatexRunOptions, LatexResult, BibtexOptions, MakeindexOptions, ToolResult } from './types.js';
13
+ /** The local references (href="#id") in an SVG that name no element in it. */
14
+ export declare function danglingRefs(svg: string): string[];
15
+ /** Where MetaPost looks for each file type (docs/06 §2). */
16
+ export declare const SEARCH_PATHS: Record<number, string[]>;
17
+ export interface CoreEnv {
18
+ mplibFactory: MplibFactory;
19
+ texFactory?: TexFactory;
20
+ /** luatex.wasm, same module interface as tex.wasm; needed for engine 'lualatex' / 'luatex' */
21
+ luatexFactory?: TexFactory;
22
+ dvisvgmFactory?: DvisvgmFactory;
23
+ /** the Ghostscript module for dvisvgm's PostScript (ghostscript.ts), when enabled; null if it cannot be loaded */
24
+ ghostscript?: () => Promise<Ghostscript | null>;
25
+ /** bibtex.wasm and makeindex.wasm, loaded on first use; undefined if this build has none */
26
+ tools?: (name: 'bibtex' | 'makeindex') => Promise<TexFactory | undefined>;
27
+ /** bundles merged into /texmf (browser, or Node without texmfDir) */
28
+ bundles?: BundleSet;
29
+ /** Node: real directory mounted at /texmf with NODEFS */
30
+ texmfDir?: string;
31
+ options: MetaPostOptions;
32
+ onProgress?: (e: ProgressEvent) => void;
33
+ onLog?: (line: string) => void;
34
+ /** where every part of a run reports (docs/08 §4); silent if absent */
35
+ logger?: Logger;
36
+ }
37
+ export declare class MetaPostCore {
38
+ private env;
39
+ M: MplibModule;
40
+ private cache;
41
+ private bridge?;
42
+ readonly version: {
43
+ metapost: string;
44
+ tex: string;
45
+ build: string;
46
+ };
47
+ private userFiles;
48
+ /**
49
+ * luaotfload's font cache (TEXMF_VAR), carried from one LuaTeX run to the
50
+ * next. Parsing an OpenType face costs about a second, and every TeX run
51
+ * gets a fresh filesystem, so without this each render pays that again.
52
+ */
53
+ private texmfVar;
54
+ private get logger();
55
+ constructor(env: CoreEnv);
56
+ init(): Promise<void>;
57
+ private progress;
58
+ /** The errors and warnings of a finished run, one record each; a MetaPost help paragraph is indented under its error. */
59
+ private report;
60
+ private formatId;
61
+ private installTexmf;
62
+ /** Restore the font cache this instance has accumulated (LuaTeX runs only). */
63
+ private installTexmfVar;
64
+ /**
65
+ * Start the font cache from the prebuilt name database, if the tree has one
66
+ * (the `opentype` bundle, or a mounted texmfDir built by make-fontdb). Its
67
+ * paths are the /texmf ones every instance sees; luaotfload checks only the
68
+ * index version, and rescans by itself when a lookup misses.
69
+ */
70
+ private seedFontDb;
71
+ /** Keep whatever luaotfload wrote, so the next run starts warm. */
72
+ private collectTexmfVar;
73
+ private copyUserFiles;
74
+ /** Last-chance file resolution when the C search failed: consult bundles, then the user hook. */
75
+ private findFile;
76
+ private findFileImpl;
77
+ private chain;
78
+ private misses;
79
+ private stats;
80
+ private engine;
81
+ private texDiagnostics;
82
+ private makeText;
83
+ private runScript;
84
+ addFiles(files: Record<string, string | Uint8Array>): void;
85
+ /**
86
+ * Take files off this instance that addFiles (or a run's `files`) put there, named as they were
87
+ * given; with no names, all of them. They otherwise stay for the instance's lifetime, so a host
88
+ * typesetting one document after another would hand the first one's .aux to the next.
89
+ */
90
+ removeFiles(names?: string[]): void;
91
+ clearCache(): void;
92
+ run(source: string, ro?: RunOptions): Promise<RunResult>;
93
+ private lastTexLog;
94
+ private recentOutput;
95
+ /**
96
+ * Typeset a complete LaTeX (or plain TeX) document with tex.wasm and convert
97
+ * every page to SVG with dvisvgm.wasm — the TikZ/PGF pipeline. Text becomes
98
+ * glyph outlines unless fonts: 'woff2' is requested.
99
+ */
100
+ latex(source: string, lo?: LatexRunOptions): Promise<LatexResult>;
101
+ /**
102
+ * BibTeX (bibtex.wasm) on the .aux a latex() run wrote: doc.bbl and doc.blg come back in
103
+ * artifacts, for the next latex() run. Like latex(), a fresh module each time.
104
+ */
105
+ bibtex(bo?: BibtexOptions): Promise<ToolResult>;
106
+ /** makeindex (makeindex.wasm) on the .idx a latex() run wrote: doc.ind and doc.ilg come back in artifacts. */
107
+ makeindex(mo?: MakeindexOptions): Promise<ToolResult>;
108
+ /** One run of a TeX Live utility: what it wrote in /work comes back, its transcript as diagnostics. */
109
+ private runTool;
110
+ private hasSnapshot;
111
+ private typeset;
112
+ private runMetaPost;
113
+ /**
114
+ * Scan the job and every `input`-ed file reachable from it (lexically),
115
+ * splicing each input file's blocks in at the line of the `input` statement
116
+ * so the verbatimtex chain seen by the pre-scan matches the run's order.
117
+ */
118
+ private scanAll;
119
+ private resolveInput;
120
+ }
121
+ /** Errors (`! ...` + `l.N`) and package warnings from a TeX transcript, attributed to the document. */
122
+ export declare function parseTexLogDocument(log: string, file: string): Diagnostic[];
123
+ /** Does a LaTeX source need LuaTeX? (TikZ graphdrawing, \directlua, luacode.) Used by engine 'auto'. */
124
+ export declare function needsLuaTeX(source: string): boolean;