Oregami
Repositories/oxedyne/daimond

oxedyne/daimond/dev/probe_typstproj.mjs

3.7 KiB, 1 run

created by r2519314175:107, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1// probe_typstproj.mjs — establish, empirically, what the vendored compiler will accept.
2//
3// Not a verifier. Four questions had to be answered before any design could be
4// written, and guessing at them is how the single-file bug got shipped:
5//
6// 1. Where is the compiler's project root? `compile()` takes no root argument,
7// so the answer decides whether "/" is the root and shadow paths are
8// root-relative.
9// 2. Does a relative import that climbs (`../style/x.typ`) resolve against the
10// IMPORTING file's directory, as it does on the CLI?
11// 3. Does an absolute reference (`/assets/x.svg`) resolve against the root?
12// 4. Does this build accept font bytes AFTER `build()` -- `TypstFontResolverBuilder`
13// plus `TypstCompiler.set_fonts` -- and what does `get_font_info` report?
14import { open } from './harness.mjs';
15
16const s = await open({ name: 'typstprobe' });
17const p = s.page;
18await p.waitForTimeout(1200);
19await p.evaluate(async () => {
20 const mod = await import('../pkg/oxedyne_daimond.js');
21 mod.set_locked_packs('');
22});
23
24const out = await p.evaluate(async () => {
25 const VENDOR = new URL('/vendor/typst/', location.href);
26 const mod = await import(new URL('typst_ts_web_compiler.mjs', VENDOR).href);
27 await mod.default(new URL('typst_ts_web_compiler_bg.wasm', VENDOR));
28 const b = new mod.TypstCompilerBuilder();
29 b.set_dummy_access_model();
30 const FONTS = ['LibertinusSerif-Regular.otf', 'LibertinusSerif-Bold.otf',
31 'LibertinusSerif-Italic.otf', 'LibertinusSerif-BoldItalic.otf', 'NewCMMath-Regular.otf'];
32 const bytes = {};
33 for (const n of FONTS) {
34 const r = await fetch(new URL('fonts/' + n, VENDOR));
35 bytes[n] = new Uint8Array(await r.arrayBuffer());
36 await b.add_raw_font(bytes[n]);
37 }
38 const c = await b.build();
39 const res = {};
40
41 const run = (main) => {
42 try {
43 const r = c.compile(main, undefined, 'pdf', 3);
44 const pdf = r instanceof Uint8Array ? r : (r && (r.result || r.artifact));
45 if (pdf && pdf.length > 4) return { bytes: pdf.length };
46 return { err: JSON.stringify(r && r.diagnostics ? r.diagnostics : r).slice(0, 400) };
47 } catch (e) { return { err: 'threw: ' + (e && e.message ? e.message : e) }; }
48 };
49
50 // Q1+Q2+Q3 in one document: main sits in a sub-directory, imports a sibling,
51 // climbs to a sibling directory, and names an asset absolutely.
52 c.reset_shadow();
53 c.add_source('/book/main.typ', [
54 '#import "tpl.typ": tag',
55 '#import "../style/glo.typ": glo',
56 '= #tag() #glo()',
57 '#include "chap01.typ"',
58 '#image("/assets/dot.svg", width: 10pt)',
59 ].join('\n'));
60 c.add_source('/book/tpl.typ', '#let tag() = [T]\n');
61 c.add_source('/book/chap01.typ', '== Chapter one\n\nText.\n');
62 c.add_source('/style/glo.typ', '#let glo() = [G]\n');
63 c.map_shadow('/assets/dot.svg', new TextEncoder().encode(
64 '<svg xmlns="http://www.w3.org/2000/svg" width="4" height="4"><rect width="4" height="4"/></svg>'));
65 res.projectAtSlashRoot = run('/book/main.typ');
66
67 // The same, with the asset withheld: does it say something usable?
68 c.unmap_shadow('/assets/dot.svg');
69 res.assetWithheld = run('/book/main.typ');
70
71 // Q4: fonts after build.
72 try {
73 const fb = new mod.TypstFontResolverBuilder();
74 res.fontInfo = JSON.stringify(fb.get_font_info(bytes['LibertinusSerif-Regular.otf'])).slice(0, 600);
75 for (const n of FONTS) fb.add_raw_font(bytes[n]);
76 const rr = await fb.build();
77 c.set_fonts(rr);
78 res.setFonts = 'ok';
79 res.loaded = c.get_loaded_fonts().slice(0, 12);
80 } catch (e) { res.setFonts = 'threw: ' + (e && e.message ? e.message : e); }
81
82 // And does a document naming an unknown font still compile (silent fallback)?
83 c.reset_shadow();
84 c.add_source('/m.typ', '#set text(font: "Radley")\n= Hello\n');
85 res.unknownFont = run('/m.typ');
86
87 return res;
88});
89
90console.log(JSON.stringify(out, null, 2));
91await s.close();