@vedivad/typst-web-service 0.9.0 → 0.9.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/dist/index.d.ts +14 -6
- package/dist/index.js +21 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -312,17 +312,24 @@ interface TypstProjectOptions {
|
|
|
312
312
|
*/
|
|
313
313
|
analyzerUriRoot?: string;
|
|
314
314
|
/**
|
|
315
|
-
*
|
|
315
|
+
* Scheduling for auto-compiles after VFS mutations. Mutations debounce by
|
|
316
|
+
* `debounceMs`; `maxWaitMs` caps how long the debounce can keep deferring
|
|
317
|
+
* during sustained edits so the user still sees progress.
|
|
318
|
+
*/
|
|
319
|
+
autoCompile?: AutoCompileOptions;
|
|
320
|
+
}
|
|
321
|
+
interface AutoCompileOptions {
|
|
322
|
+
/**
|
|
323
|
+
* Idle time (ms) after the last VFS mutation before a compile fires.
|
|
316
324
|
* Default: 0 — compile fires on the next macrotask. Set higher (e.g. 150) to
|
|
317
325
|
* coalesce rapid edits.
|
|
318
326
|
*/
|
|
319
|
-
|
|
327
|
+
debounceMs?: number;
|
|
320
328
|
/**
|
|
321
|
-
* Maximum time (ms)
|
|
322
|
-
*
|
|
323
|
-
* throttle — only debounce applies).
|
|
329
|
+
* Maximum time (ms) the debounce is allowed to defer a compile during
|
|
330
|
+
* sustained mutation bursts. Default: 0 (no cap — pure debounce).
|
|
324
331
|
*/
|
|
325
|
-
|
|
332
|
+
maxWaitMs?: number;
|
|
326
333
|
}
|
|
327
334
|
/**
|
|
328
335
|
* Coordinates a compiler + analyzer pair for multi-file Typst projects.
|
|
@@ -354,6 +361,7 @@ declare class TypstProject {
|
|
|
354
361
|
private _lastResult;
|
|
355
362
|
private _entry;
|
|
356
363
|
private destroyed;
|
|
364
|
+
private invokeListener;
|
|
357
365
|
constructor(options: TypstProjectOptions);
|
|
358
366
|
/**
|
|
359
367
|
* Schedule an auto-compile after VFS mutations. Coalesces rapid calls via
|
package/dist/index.js
CHANGED
|
@@ -299,26 +299,26 @@ var CompileScheduler = class {
|
|
|
299
299
|
this.options = options;
|
|
300
300
|
}
|
|
301
301
|
debounceTimer = null;
|
|
302
|
-
|
|
302
|
+
maxWaitTimer = null;
|
|
303
303
|
lastFireTime = 0;
|
|
304
304
|
schedule(callback) {
|
|
305
305
|
if (this.debounceTimer) {
|
|
306
306
|
clearTimeout(this.debounceTimer);
|
|
307
307
|
this.debounceTimer = null;
|
|
308
308
|
}
|
|
309
|
-
const delay = Math.max(0, this.options.
|
|
309
|
+
const delay = Math.max(0, this.options.debounceMs ?? 0);
|
|
310
310
|
this.debounceTimer = setTimeout(() => {
|
|
311
311
|
this.debounceTimer = null;
|
|
312
312
|
this.fire(callback);
|
|
313
313
|
}, delay);
|
|
314
|
-
const
|
|
315
|
-
if (
|
|
314
|
+
const maxWait = this.options.maxWaitMs;
|
|
315
|
+
if (maxWait != null && maxWait > 0 && !this.maxWaitTimer) {
|
|
316
316
|
const wait = Math.max(
|
|
317
317
|
0,
|
|
318
|
-
|
|
318
|
+
maxWait - (performance.now() - this.lastFireTime)
|
|
319
319
|
);
|
|
320
|
-
this.
|
|
321
|
-
this.
|
|
320
|
+
this.maxWaitTimer = setTimeout(() => {
|
|
321
|
+
this.maxWaitTimer = null;
|
|
322
322
|
if (this.debounceTimer) {
|
|
323
323
|
clearTimeout(this.debounceTimer);
|
|
324
324
|
this.debounceTimer = null;
|
|
@@ -333,9 +333,9 @@ var CompileScheduler = class {
|
|
|
333
333
|
clearTimeout(this.debounceTimer);
|
|
334
334
|
this.debounceTimer = null;
|
|
335
335
|
}
|
|
336
|
-
if (this.
|
|
337
|
-
clearTimeout(this.
|
|
338
|
-
this.
|
|
336
|
+
if (this.maxWaitTimer) {
|
|
337
|
+
clearTimeout(this.maxWaitTimer);
|
|
338
|
+
this.maxWaitTimer = null;
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
341
|
fire(callback) {
|
|
@@ -376,6 +376,13 @@ var TypstProject = class {
|
|
|
376
376
|
_lastResult;
|
|
377
377
|
_entry;
|
|
378
378
|
destroyed = false;
|
|
379
|
+
invokeListener(listener, result) {
|
|
380
|
+
try {
|
|
381
|
+
listener(result);
|
|
382
|
+
} catch (err) {
|
|
383
|
+
console.error("[typst] compile listener threw:", err);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
379
386
|
constructor(options) {
|
|
380
387
|
this.compiler = options.compiler;
|
|
381
388
|
this.analyzer = options.analyzer;
|
|
@@ -384,8 +391,8 @@ var TypstProject = class {
|
|
|
384
391
|
);
|
|
385
392
|
this._entry = normalizePath(options.entry ?? DEFAULT_ENTRY);
|
|
386
393
|
this.scheduler = new CompileScheduler({
|
|
387
|
-
|
|
388
|
-
|
|
394
|
+
debounceMs: options.autoCompile?.debounceMs,
|
|
395
|
+
maxWaitMs: options.autoCompile?.maxWaitMs
|
|
389
396
|
});
|
|
390
397
|
}
|
|
391
398
|
/**
|
|
@@ -533,11 +540,7 @@ var TypstProject = class {
|
|
|
533
540
|
onCompile(listener) {
|
|
534
541
|
this.compileListeners.add(listener);
|
|
535
542
|
if (this._lastResult !== void 0) {
|
|
536
|
-
|
|
537
|
-
listener(this._lastResult);
|
|
538
|
-
} catch (err) {
|
|
539
|
-
console.error("[typst] compile listener threw:", err);
|
|
540
|
-
}
|
|
543
|
+
this.invokeListener(listener, this._lastResult);
|
|
541
544
|
}
|
|
542
545
|
return () => {
|
|
543
546
|
this.compileListeners.delete(listener);
|
|
@@ -567,11 +570,7 @@ var TypstProject = class {
|
|
|
567
570
|
if (version === this.compileVersion) {
|
|
568
571
|
this._lastResult = result;
|
|
569
572
|
for (const listener of this.compileListeners) {
|
|
570
|
-
|
|
571
|
-
listener(result);
|
|
572
|
-
} catch (err) {
|
|
573
|
-
console.error("[typst] compile listener threw:", err);
|
|
574
|
-
}
|
|
573
|
+
this.invokeListener(listener, result);
|
|
575
574
|
}
|
|
576
575
|
}
|
|
577
576
|
return result;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/analyzer.ts","../src/rpc.ts","../src/identifiers.ts","../src/compiler.ts","../src/formatter.ts","../src/compile-scheduler.ts","../src/project.ts","../src/renderer.ts"],"sourcesContent":["import * as Comlink from \"comlink\";\nimport type {\n LspCompletionResponse,\n LspHover,\n LspPosition,\n} from \"./analyzer-types.js\";\nimport type { AnalyzerWorker } from \"./analyzer-worker.js\";\nimport { createAnalyzerWorker } from \"./rpc.js\";\n\nexport interface TypstAnalyzerOptions {\n /**\n * Explicit Worker instance. When omitted, an inlined blob worker is created automatically.\n * Use this for Vite apps:\n * `await TypstAnalyzer.create({ worker: new Worker(new URL('typst-web-service/analyzer-worker', import.meta.url), { type: 'module' }) })`\n */\n worker?: Worker;\n /**\n * URL to the tinymist WASM binary.\n * Required — there is no default CDN URL for tinymist-web.\n */\n wasmUrl: string;\n}\n\n/**\n * Manages a tinymist language server in a Web Worker. Provides LSP-based\n * completion and hover for Typst documents.\n *\n * const analyzer = await TypstAnalyzer.create({ wasmUrl: '...' });\n */\nexport class TypstAnalyzer {\n private readonly proxy: Comlink.Remote<AnalyzerWorker>;\n private readonly worker: Worker;\n private versionCounter = 0;\n /**\n * Last content pushed to the worker per URI. Presence is the source of\n * truth for \"is this URI opened on the worker?\"; value drives own-RPC dedup.\n */\n private readonly content = new Map<string, string>();\n\n private constructor(\n worker: Worker,\n proxy: Comlink.Remote<AnalyzerWorker>,\n ) {\n this.worker = worker;\n this.proxy = proxy;\n }\n\n static async create(options: TypstAnalyzerOptions): Promise<TypstAnalyzer> {\n const worker = options.worker ?? createAnalyzerWorker();\n const proxy = Comlink.wrap<AnalyzerWorker>(worker);\n const absoluteWasmUrl = new URL(options.wasmUrl, globalThis.location?.href)\n .href;\n\n const analyzer = new TypstAnalyzer(worker, proxy);\n\n await proxy.init(absoluteWasmUrl);\n\n return analyzer;\n }\n\n async didOpen(uri: string, content: string): Promise<void> {\n this.content.set(uri, content);\n await this.proxy.didOpen(uri, content);\n }\n\n async didClose(uri: string): Promise<void> {\n if (!this.content.delete(uri)) return;\n await this.proxy.didClose(uri);\n }\n\n /**\n * Notify the analyzer that a document has changed. Skips the RPC when the\n * content matches what the worker last saw.\n */\n async didChange(uri: string, content: string): Promise<void> {\n if (!this.content.has(uri)) {\n await this.didOpen(uri, content);\n return;\n }\n if (this.content.get(uri) === content) return;\n this.content.set(uri, content);\n const version = ++this.versionCounter;\n await this.proxy.didChange(uri, version, content);\n }\n\n /**\n * Batch document changes. Splits inputs into opens (first-time URIs) and\n * changes (already-open URIs) and sends them in a single worker roundtrip.\n * Skips unchanged documents; returns without an RPC if nothing is pending.\n */\n async didChangeMany(docs: Record<string, string>): Promise<void> {\n const opens: Array<{ uri: string; content: string }> = [];\n const changes: Array<{ uri: string; version: number; content: string }> =\n [];\n for (const [uri, content] of Object.entries(docs)) {\n if (!this.content.has(uri)) {\n opens.push({ uri, content });\n this.content.set(uri, content);\n } else if (this.content.get(uri) !== content) {\n changes.push({ uri, version: ++this.versionCounter, content });\n this.content.set(uri, content);\n }\n }\n if (opens.length === 0 && changes.length === 0) return;\n await this.proxy.didChangeMany(opens, changes);\n }\n\n /**\n * Batch document closes. Filters to currently-open URIs and sends the set\n * in a single worker roundtrip.\n */\n async didCloseMany(uris: string[]): Promise<void> {\n const toClose: string[] = [];\n for (const uri of uris) {\n if (this.content.delete(uri)) toClose.push(uri);\n }\n if (toClose.length === 0) return;\n await this.proxy.didCloseMany(toClose);\n }\n\n /**\n * Request completion at `position` for `uri`, with `content` as the current\n * document state. Bundles the didChange notification with the request in one\n * worker roundtrip; degrades to a plain completion request when the worker\n * already has this exact content.\n */\n async completion(\n uri: string,\n content: string,\n position: LspPosition,\n ): Promise<LspCompletionResponse> {\n if (this.content.get(uri) === content) {\n return this.proxy.completion(uri, position);\n }\n const isOpen = this.content.has(uri);\n this.content.set(uri, content);\n const version = ++this.versionCounter;\n return this.proxy.completionWithDoc(\n uri,\n version,\n content,\n position,\n isOpen ? \"change\" : \"open\",\n );\n }\n\n /**\n * Request hover at `position` for `uri`, with `content` as the current\n * document state. Bundles the didChange notification with the request in one\n * worker roundtrip; degrades to a plain hover request when the worker\n * already has this exact content.\n */\n async hover(\n uri: string,\n content: string,\n position: LspPosition,\n ): Promise<LspHover | null> {\n if (this.content.get(uri) === content) {\n return this.proxy.hover(uri, position);\n }\n const isOpen = this.content.has(uri);\n this.content.set(uri, content);\n const version = ++this.versionCounter;\n return this.proxy.hoverWithDoc(\n uri,\n version,\n content,\n position,\n isOpen ? \"change\" : \"open\",\n );\n }\n\n destroy(): void {\n this.proxy[Comlink.releaseProxy]();\n this.worker.terminate();\n }\n}\n","// Injected at build time by tsup (see tsup.config.ts)\ndeclare const __WORKER_CODE__: string;\ndeclare const __ANALYZER_WORKER_CODE__: string;\n\n/** Create a Worker from an inlined code string, auto-revoking the blob URL on terminate. */\nexport function createBlobWorker(code: string): Worker {\n const blob = new Blob([code], { type: \"application/javascript\" });\n const url = URL.createObjectURL(blob);\n const worker = new Worker(url);\n const origTerminate = worker.terminate.bind(worker);\n worker.terminate = () => {\n origTerminate();\n URL.revokeObjectURL(url);\n };\n return worker;\n}\n\n/** Create a blob Worker from the inlined compiler worker code. */\nexport function createWorker(): Worker {\n return createBlobWorker(__WORKER_CODE__);\n}\n\n/** Create a blob Worker from the inlined analyzer worker code. */\nexport function createAnalyzerWorker(): Worker {\n return createBlobWorker(__ANALYZER_WORKER_CODE__);\n}\n","/**\n * Two addressing schemes live in this codebase. This file is the only place\n * that knows how they relate. Keeping the vocabulary and conversions colocated\n * means a new contributor can read one file and understand the model.\n *\n * 1. Path — \"/main.typ\". Always leading-slash, always forward slashes.\n * Used by the compiler VFS, the `TypstProject` public API,\n * and the `typstFilePath` facet. Addresses a file within\n * the project.\n *\n * 2. AnalyzerUri — \"untitled:project/main.typ\". What tinymist's LSP expects.\n * Derived from a Path plus the analyzer URI root.\n *\n * The types below are type aliases, not branded/opaque types. That's\n * deliberate: callers can pass string literals where a Path is expected\n * without wrapping, and the aliases only serve as self-documenting\n * signatures. Ingress points still need to call `normalizePath` to defend\n * against un-normalized input — the alias does not imply the string has\n * been normalized.\n */\n\n/** `/path/to/file.typ` — leading-slash, forward slashes only. */\nexport type Path = string;\n\n/** `untitled:project/path/to/file.typ` — what tinymist's LSP consumes. */\nexport type AnalyzerUri = string;\n\n/** Ensure a path starts with a leading slash. Idempotent. */\nexport function normalizePath(path: string): Path {\n return path.startsWith(\"/\") ? path : `/${path}`;\n}\n\n/**\n * Normalize an analyzer URI root. Ensures leading slash, strips trailing\n * slashes. Special-cases \"/\" → \"\" so URIs don't end up with a leading\n * `untitled://`.\n */\nexport function normalizeRoot(rootPath: string): string {\n const root = normalizePath(rootPath);\n return root === \"/\" ? \"\" : root.replace(/\\/+$/, \"\");\n}\n\n/**\n * Build the analyzer URI for a given project path. `root` is expected to\n * already be normalized (see `normalizeRoot`).\n *\n * pathToAnalyzerUri(\"/main.typ\", \"/project\") -> \"untitled:project/main.typ\"\n */\nexport function pathToAnalyzerUri(path: Path, root: string): AnalyzerUri {\n const bare = root.replace(/^\\//, \"\");\n return `untitled:${bare}${normalizePath(path)}`;\n}\n","import * as Comlink from \"comlink\";\nimport { createWorker } from \"./rpc.js\";\nimport type { DiagnosticMessage } from \"./types.js\";\nimport type { CompilerWorker } from \"./compiler-worker.js\";\n\ndeclare const __TYPST_TS_WEB_COMPILER_VERSION__: string;\n\nexport interface CompileResult {\n diagnostics: DiagnosticMessage[];\n /** Vector artifact bytes from the compiler, usable with TypstRenderer for SVG rendering. */\n vector?: Uint8Array;\n}\n\nexport interface TypstCompilerOptions {\n /**\n * Explicit Worker instance. When omitted, an inlined blob worker is created automatically.\n * Use this for Vite apps to get proper source maps:\n * `await TypstCompiler.create({ worker: new Worker(new URL('typst-web-service/compiler-worker', import.meta.url)) })`\n */\n worker?: Worker;\n /**\n * URL to the typst-ts-web-compiler WASM binary.\n * Defaults to the matching version on jsDelivr CDN.\n * Override with a local asset URL for offline support or faster load:\n * `new URL('@myriaddreamin/typst-ts-web-compiler/pkg/typst_ts_web_compiler_bg.wasm', import.meta.url).href`\n */\n wasmUrl?: string;\n /** Font URLs to load into the Typst compiler. Defaults to Roboto from jsDelivr. */\n fonts?: string[];\n /**\n * Enable fetching @preview/ packages from packages.typst.org on demand.\n * Default: true.\n */\n packages?: boolean;\n}\n\nconst DEFAULT_FONTS = [\n \"https://cdn.jsdelivr.net/npm/roboto-font@0.1.0/fonts/Roboto/roboto-regular-webfont.ttf\",\n];\n\nconst DEFAULT_WASM_URL = `https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-web-compiler@${__TYPST_TS_WEB_COMPILER_VERSION__}/pkg/typst_ts_web_compiler_bg.wasm`;\n\n/**\n * Manages a Typst compiler worker. Create one instance and share it across\n * all extensions (linter, autocomplete, preview, etc.).\n *\n * await TypstCompiler.create() // blob worker, defaults\n * await TypstCompiler.create({ wasmUrl: '...' }) // blob worker, custom WASM\n * await TypstCompiler.create({ worker: myWorker }) // explicit Worker (Vite)\n * await TypstCompiler.create({ worker: myWorker, fonts: [...] }) // explicit Worker + options\n */\nexport class TypstCompiler {\n private readonly proxy: Comlink.Remote<CompilerWorker>;\n private readonly worker: Worker;\n private readonly encoder = new TextEncoder();\n /** Last text content pushed per path. Drives own-RPC dedup. Invalidated by binary writes. */\n private readonly content = new Map<string, string>();\n\n private constructor(\n worker: Worker,\n proxy: Comlink.Remote<CompilerWorker>,\n ) {\n this.worker = worker;\n this.proxy = proxy;\n }\n\n static async create(\n options: TypstCompilerOptions = {},\n ): Promise<TypstCompiler> {\n const worker = options.worker ?? createWorker();\n const proxy = Comlink.wrap<CompilerWorker>(worker);\n\n await proxy.init(\n options.wasmUrl ?? DEFAULT_WASM_URL,\n options.fonts ?? DEFAULT_FONTS,\n options.packages ?? true,\n );\n\n return new TypstCompiler(worker, proxy);\n }\n\n /**\n * Compile whatever is currently in the VFS (populated via\n * setText/setBinary/setJson/setMany). Defaults to compiling \"/main.typ\";\n * override with `entry`.\n */\n compile(entry?: string): Promise<CompileResult> {\n return this.proxy.compile(entry);\n }\n\n /**\n * Compile to PDF. Operates on whatever is currently in the VFS (populated\n * via setText/setBinary/setJson/setMany). Defaults to compiling \"/main.typ\";\n * override with `entry`.\n */\n compilePdf(entry?: string): Promise<Uint8Array> {\n return this.proxy.compilePdf(entry);\n }\n\n /**\n * Add or overwrite a text file in the virtual compiler filesystem. Skips\n * the worker RPC when `source` matches the last value pushed for `path`.\n */\n async setText(path: string, source: string): Promise<void> {\n if (this.content.get(path) === source) return;\n this.content.set(path, source);\n return this.proxy.mapShadow(path, this.encoder.encode(source));\n }\n\n /** Add or overwrite a JSON file in the virtual compiler filesystem. */\n setJson(\n path: string,\n value: unknown,\n replacer?: (this: unknown, key: string, value: unknown) => unknown,\n space?: string | number,\n ): Promise<void> {\n return this.setText(path, JSON.stringify(value, replacer, space));\n }\n\n /**\n * Add or overwrite multiple files in the virtual compiler filesystem in a\n * single worker roundtrip. Strings are UTF-8 encoded; Uint8Arrays are\n * passed through. Text entries unchanged since their last push are skipped;\n * binary entries always push and invalidate the text cache for their path.\n */\n async setMany(files: Record<string, string | Uint8Array>): Promise<void> {\n const encoded: Record<string, Uint8Array> = {};\n for (const [path, content] of Object.entries(files)) {\n if (typeof content === \"string\") {\n if (this.content.get(path) === content) continue;\n this.content.set(path, content);\n encoded[path] = this.encoder.encode(content);\n } else {\n this.content.delete(path);\n encoded[path] = content;\n }\n }\n if (Object.keys(encoded).length === 0) return;\n return this.proxy.mapShadowMany(encoded);\n }\n\n /** Add or overwrite a binary file in the virtual compiler filesystem. */\n setBinary(\n path: string,\n content: ArrayBuffer | ArrayBufferView,\n ): Promise<void> {\n this.content.delete(path);\n const bytes =\n content instanceof ArrayBuffer\n ? new Uint8Array(content)\n : new Uint8Array(\n content.buffer,\n content.byteOffset,\n content.byteLength,\n );\n return this.proxy.mapShadow(path, bytes);\n }\n\n /** Remove a file from the virtual compiler filesystem. */\n remove(path: string): Promise<void> {\n this.content.delete(path);\n return this.proxy.unmapShadow(path);\n }\n\n /** Clear all virtual files from the compiler filesystem. */\n clear(): Promise<void> {\n this.content.clear();\n return this.proxy.resetShadow();\n }\n\n destroy(): void {\n this.proxy[Comlink.releaseProxy]();\n this.worker.terminate();\n }\n}\n","export interface FormatConfig {\n /** Number of spaces per indentation level. Default: 2 */\n tab_spaces?: number;\n /** Maximum line width. Default: 80 */\n max_width?: number;\n /** Maximum consecutive blank lines allowed. */\n blank_lines_upper_bound?: number;\n /** Collapse consecutive whitespace in markup to a single space. */\n collapse_markup_spaces?: boolean;\n /** Sort import items alphabetically. */\n reorder_import_items?: boolean;\n /** Wrap text in markup to fit within max_width. Implies collapse_markup_spaces. */\n wrap_text?: boolean;\n}\n\nexport interface FormatRangeResult {\n /** Start index (UTF-16) of the actual formatted range. */\n start: number;\n /** End index (UTF-16) of the actual formatted range. */\n end: number;\n /** The formatted text for the range. */\n text: string;\n}\n\ntype TypstyleModule = typeof import(\"@typstyle/typstyle-wasm-bundler\");\n\nlet typstylePromise: Promise<TypstyleModule> | null = null;\n\nfunction getTypstyle(): Promise<TypstyleModule> {\n if (!typstylePromise) {\n typstylePromise = import(\"@typstyle/typstyle-wasm-bundler\").catch((err) => {\n typstylePromise = null;\n throw err;\n });\n }\n return typstylePromise;\n}\n\n/**\n * Typst code formatter powered by typstyle.\n *\n * Runs on the main thread — typstyle is lightweight and fast.\n * The WASM module is loaded lazily on first format call.\n * Requires a bundler that supports WASM imports (e.g. Vite, webpack).\n *\n * const formatter = TypstFormatter.create({ tab_spaces: 2, max_width: 80 });\n * const formatted = await formatter.format(source);\n */\nexport class TypstFormatter {\n private config: FormatConfig;\n\n private constructor(config: FormatConfig = {}) {\n this.config = config;\n // Eagerly start loading WASM so it's ready by first use.\n // Swallow preload errors — they'll surface on first format() call.\n getTypstyle().catch(() => {});\n }\n\n static create(config: FormatConfig = {}): TypstFormatter {\n return new TypstFormatter(config);\n }\n\n /** Format an entire Typst source string. */\n async format(source: string): Promise<string> {\n const typstyle = await getTypstyle();\n return typstyle.format(source, this.config);\n }\n\n /** Format a range within a Typst source string. Indices are UTF-16 code units. */\n async formatRange(\n source: string,\n start: number,\n end: number,\n ): Promise<FormatRangeResult> {\n const typstyle = await getTypstyle();\n const result = typstyle.format_range(source, start, end, this.config);\n return { start: result.start, end: result.end, text: result.text };\n }\n}\n","export interface CompileSchedulerOptions {\n /** Minimum idle time (ms) after the last request before firing. Default: 0. */\n debounceDelay?: number;\n /**\n * Maximum time (ms) between fires during continuous requests. Guarantees\n * a run at least this often so users see progress while typing. Default: 0\n * (no throttle).\n */\n throttleDelay?: number;\n}\n\n/**\n * Debounce + throttle helper for coalescing compile requests. A burst of\n * `schedule(cb)` calls within `debounceDelay` collapses into one fire; during\n * sustained bursts, `throttleDelay` guarantees a fire no less often than that.\n */\nexport class CompileScheduler {\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private throttleTimer: ReturnType<typeof setTimeout> | null = null;\n private lastFireTime = 0;\n\n constructor(private readonly options: CompileSchedulerOptions = {}) {}\n\n schedule(callback: () => void): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n const delay = Math.max(0, this.options.debounceDelay ?? 0);\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.fire(callback);\n }, delay);\n\n const throttle = this.options.throttleDelay;\n if (throttle != null && throttle > 0 && !this.throttleTimer) {\n const wait = Math.max(\n 0,\n throttle - (performance.now() - this.lastFireTime),\n );\n this.throttleTimer = setTimeout(() => {\n this.throttleTimer = null;\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n this.fire(callback);\n }\n }, wait);\n }\n }\n\n /** Cancel any pending scheduled fire without calling the callback. */\n cancel(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n if (this.throttleTimer) {\n clearTimeout(this.throttleTimer);\n this.throttleTimer = null;\n }\n }\n\n private fire(callback: () => void): void {\n this.lastFireTime = performance.now();\n callback();\n }\n}\n","import type { TypstAnalyzer } from \"./analyzer.js\";\nimport type {\n LspCompletionResponse,\n LspHover,\n LspPosition,\n} from \"./analyzer-types.js\";\nimport { CompileScheduler } from \"./compile-scheduler.js\";\nimport type { CompileResult, TypstCompiler } from \"./compiler.js\";\nimport {\n normalizePath,\n normalizeRoot,\n type Path,\n pathToAnalyzerUri,\n} from \"./identifiers.js\";\n\nexport interface TypstProjectOptions {\n compiler: TypstCompiler;\n /**\n * Optional analyzer. When provided, text file operations also sync with the\n * analyzer so completions / hover reflect the current state.\n */\n analyzer?: TypstAnalyzer;\n /** Default entry file path. Default: \"/main.typ\". */\n entry?: string;\n /**\n * Prefix used to build the `untitled:` URIs handed to the analyzer.\n * Default: \"/project\". A path of `/main.typ` becomes\n * `untitled:project/main.typ`. Only affects URI construction — the compiler\n * and project VFS use the raw paths unchanged.\n */\n analyzerUriRoot?: string;\n /**\n * Idle time (ms) after the last VFS mutation before an auto-compile fires.\n * Default: 0 — compile fires on the next macrotask. Set higher (e.g. 150) to\n * coalesce rapid edits.\n */\n compileDebounceMs?: number;\n /**\n * Maximum time (ms) between auto-compiles during sustained mutation bursts.\n * Guarantees progress while the user is actively typing. Default: 0 (no\n * throttle — only debounce applies).\n */\n compileThrottleMs?: number;\n}\n\nconst DEFAULT_ENTRY = \"/main.typ\";\nconst DEFAULT_ROOT = \"/project\";\n\n/**\n * Coordinates a compiler + analyzer pair for multi-file Typst projects.\n *\n * Owns the project's virtual filesystem state. Editors push incremental\n * `setText` updates as the user types; the project mirrors those edits to\n * both the compiler's shadow VFS and the analyzer's open-document set, then\n * compiles or services LSP requests against the current state.\n *\n * const project = new TypstProject({ compiler, analyzer });\n * await project.setMany({ \"/main.typ\": \"...\", \"/utils.typ\": \"...\" });\n * const result = await project.compile();\n */\nexport type CompileListener = (result: CompileResult) => void;\n\nfunction errorAsCompileResult(\n err: unknown,\n paths: readonly string[],\n): CompileResult {\n const message = err instanceof Error ? err.message : String(err);\n return {\n diagnostics: paths.map((path) => ({\n package: \"\",\n path,\n severity: \"Error\",\n range: { startLine: 0, startCol: 0, endLine: 0, endCol: 1 },\n message,\n })),\n };\n}\n\nexport class TypstProject {\n private readonly compiler: TypstCompiler;\n private readonly analyzer?: TypstAnalyzer;\n private readonly analyzerUriRoot: string;\n /**\n * Tracked text files: path → latest content observed. Presence in this map\n * is the source of truth for \"is this a tracked text file?\"; insertion\n * order drives the `files` getter. Per-sink dedup lives in the compiler and\n * analyzer.\n */\n private readonly contentByPath = new Map<Path, string>();\n private readonly compileListeners = new Set<CompileListener>();\n private readonly scheduler: CompileScheduler;\n private compileVersion = 0;\n private _lastResult: CompileResult | undefined;\n private _entry: Path;\n private destroyed = false;\n\n constructor(options: TypstProjectOptions) {\n this.compiler = options.compiler;\n this.analyzer = options.analyzer;\n this.analyzerUriRoot = normalizeRoot(\n options.analyzerUriRoot ?? DEFAULT_ROOT,\n );\n this._entry = normalizePath(options.entry ?? DEFAULT_ENTRY);\n this.scheduler = new CompileScheduler({\n debounceDelay: options.compileDebounceMs,\n throttleDelay: options.compileThrottleMs,\n });\n }\n\n /**\n * Schedule an auto-compile after VFS mutations. Coalesces rapid calls via\n * the configured debounce/throttle. Errors surface through `onCompile`\n * listeners via a synthetic diagnostic; callers awaiting a specific compile\n * should call `compile()` directly.\n */\n private scheduleCompile(): void {\n if (this.destroyed) return;\n this.scheduler.schedule(() => {\n this.compile().catch((err) => console.error(\"[typst]\", err));\n });\n }\n\n /** Current entry file path. Assign to change the sticky entry used by subsequent `compile()` calls. */\n get entry(): Path {\n return this._entry;\n }\n\n set entry(path: Path) {\n const next = normalizePath(path);\n if (next === this._entry) return;\n this._entry = next;\n this.scheduleCompile();\n }\n\n /** Whether an analyzer is attached. */\n get hasAnalyzer(): boolean {\n return this.analyzer !== undefined;\n }\n\n /**\n * Most recent compile result, or `undefined` before the first compile has\n * settled. Useful for lazy-mounted UI that subscribes after boot and needs\n * an initial value.\n */\n get lastResult(): CompileResult | undefined {\n return this._lastResult;\n }\n\n /**\n * Snapshot of tracked text file paths, in insertion order. Updated by\n * `setText`, `setMany`, `remove`, and `clear`. Returns a fresh array — mutate\n * freely without affecting project state.\n */\n get files(): Path[] {\n return [...this.contentByPath.keys()];\n }\n\n /**\n * Current text content for a tracked file, or `undefined` if the path was\n * never written via `setText`/`setMany` (or was removed). Read-through to the\n * project's sync cache — lets consumers avoid shadowing the VFS themselves.\n */\n getText(path: Path): string | undefined {\n return this.contentByPath.get(normalizePath(path));\n }\n\n /**\n * Add or overwrite a text file. Goes to the compiler's VFS and, when an\n * analyzer is attached, to the analyzer as a document change. No-op when\n * the tracked path already has this exact content — skips both worker RPCs\n * and the auto-scheduled compile.\n */\n async setText(path: Path, content: string): Promise<void> {\n const p = normalizePath(path);\n if (this.contentByPath.get(p) === content) return;\n this.contentByPath.set(p, content);\n await Promise.all([\n this.compiler.setText(p, content),\n this.analyzer?.didChange(\n pathToAnalyzerUri(p, this.analyzerUriRoot),\n content,\n ) ?? Promise.resolve(),\n ]);\n this.scheduleCompile();\n }\n\n /**\n * Add or overwrite a JSON file. Compiler-only — the analyzer does not track\n * data files.\n */\n async setJson(path: Path, value: unknown): Promise<void> {\n await this.compiler.setJson(normalizePath(path), value);\n this.scheduleCompile();\n }\n\n /** Add or overwrite a binary file. Compiler-only. */\n async setBinary(\n path: Path,\n content: ArrayBuffer | ArrayBufferView,\n ): Promise<void> {\n await this.compiler.setBinary(normalizePath(path), content);\n this.scheduleCompile();\n }\n\n /**\n * Batch set multiple files. Strings route to both compiler and analyzer;\n * Uint8Array entries go to the compiler only. Strings matching the last\n * tracked content for their path are skipped on both sinks. Binary entries\n * always go through (no content cache, so no dedup).\n */\n async setMany(files: Record<Path, string | Uint8Array>): Promise<void> {\n const normalized: Record<Path, string | Uint8Array> = {};\n const analyzerDocs: Record<string, string> = {};\n for (const [path, content] of Object.entries(files)) {\n const p = normalizePath(path);\n if (typeof content !== \"string\") {\n normalized[p] = content;\n continue;\n }\n if (this.contentByPath.get(p) === content) continue;\n this.contentByPath.set(p, content);\n normalized[p] = content;\n analyzerDocs[pathToAnalyzerUri(p, this.analyzerUriRoot)] = content;\n }\n if (Object.keys(normalized).length === 0) return;\n await Promise.all([\n this.compiler.setMany(normalized),\n this.analyzer?.didChangeMany(analyzerDocs) ?? Promise.resolve(),\n ]);\n this.scheduleCompile();\n }\n\n /**\n * Remove a file. Always removed from the compiler's VFS; also closed on the\n * analyzer when it was previously tracked as text.\n */\n async remove(path: Path): Promise<void> {\n const p = normalizePath(path);\n const wasText = this.contentByPath.delete(p);\n await Promise.all([\n this.compiler.remove(p),\n wasText\n ? this.analyzer?.didClose(pathToAnalyzerUri(p, this.analyzerUriRoot))\n : undefined,\n ]);\n this.scheduleCompile();\n }\n\n /** Clear all files from both compiler VFS and analyzer document set. */\n async clear(): Promise<void> {\n const uris = Array.from(this.contentByPath.keys(), (p) =>\n pathToAnalyzerUri(p, this.analyzerUriRoot),\n );\n this.contentByPath.clear();\n await Promise.all([\n this.compiler.clear(),\n uris.length > 0 ? this.analyzer?.didCloseMany(uris) : undefined,\n ]);\n this.scheduleCompile();\n }\n\n /**\n * Subscribe to compile results. Fires after every `compile()` whose result is\n * still current (stale results from out-of-order concurrent compiles are\n * dropped). If a compile has already settled, the most recent result is\n * delivered synchronously so late-mounted listeners aren't stuck blank until\n * the next compile. Returns an unsubscribe function.\n */\n onCompile(listener: CompileListener): () => void {\n this.compileListeners.add(listener);\n if (this._lastResult !== undefined) {\n try {\n listener(this._lastResult);\n } catch (err) {\n console.error(\"[typst] compile listener threw:\", err);\n }\n }\n return () => {\n this.compileListeners.delete(listener);\n };\n }\n\n /**\n * Compile the current VFS state using the sticky entry. Errors from the\n * underlying compiler are converted into a synthetic error diagnostic so\n * callers and listeners always receive a `CompileResult`. Listeners are\n * notified only for the most recent compile — results from an earlier call\n * that resolves after a later one are suppressed.\n *\n * VFS mutations (`setText`, `remove`, etc.) auto-schedule a debounced\n * compile; call this directly only when you need an awaitable handle on the\n * result (e.g., to flush before rendering to PDF).\n */\n async compile(): Promise<CompileResult> {\n this.scheduler.cancel();\n const version = ++this.compileVersion;\n let result: CompileResult;\n try {\n result = await this.compiler.compile(this._entry);\n } catch (err) {\n // Spread the synthetic error across every tracked text path so the\n // diagnostic is visible no matter which file the user is viewing.\n // Falls back to the entry if nothing is tracked yet.\n const paths =\n this.contentByPath.size > 0\n ? [...this.contentByPath.keys()]\n : [this._entry];\n result = errorAsCompileResult(err, paths);\n }\n if (version === this.compileVersion) {\n this._lastResult = result;\n for (const listener of this.compileListeners) {\n try {\n listener(result);\n } catch (err) {\n console.error(\"[typst] compile listener threw:\", err);\n }\n }\n }\n return result;\n }\n\n /** Compile the current VFS state to PDF using the sticky entry. */\n compilePdf(): Promise<Uint8Array> {\n return this.compiler.compilePdf(this._entry);\n }\n\n private requireAnalyzer(operation: string): TypstAnalyzer {\n if (!this.analyzer) {\n throw new Error(`TypstProject: ${operation} requires an analyzer`);\n }\n return this.analyzer;\n }\n\n /**\n * Request completion for `path` at `position`, using `source` as the\n * current document state. One analyzer roundtrip; compiler is not touched —\n * the compile sync path writes to the compiler separately. Throws when no\n * analyzer is attached.\n */\n completion(\n path: Path,\n source: string,\n position: LspPosition,\n ): Promise<LspCompletionResponse> {\n const analyzer = this.requireAnalyzer(\"completion\");\n const p = normalizePath(path);\n this.contentByPath.set(p, source);\n return analyzer.completion(\n pathToAnalyzerUri(p, this.analyzerUriRoot),\n source,\n position,\n );\n }\n\n /**\n * Request hover for `path` at `position`, using `source` as the current\n * document state. One analyzer roundtrip; compiler is not touched. Throws\n * when no analyzer is attached.\n */\n hover(\n path: Path,\n source: string,\n position: LspPosition,\n ): Promise<LspHover | null> {\n const analyzer = this.requireAnalyzer(\"hover\");\n const p = normalizePath(path);\n this.contentByPath.set(p, source);\n return analyzer.hover(\n pathToAnalyzerUri(p, this.analyzerUriRoot),\n source,\n position,\n );\n }\n\n /**\n * Tear down the project and the services it owns. Destroys the attached\n * compiler and analyzer, drops all listeners, and clears VFS tracking state.\n * Idempotent — calling twice is a no-op. After destruction, further calls on\n * the project are not supported; construct a new one.\n *\n * If you need to share a compiler or analyzer across projects, destroy them\n * yourself and don't call this method — the project does not provide an\n * ownership toggle.\n */\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.scheduler.cancel();\n this.compileListeners.clear();\n this.contentByPath.clear();\n this._lastResult = undefined;\n this.compiler.destroy();\n this.analyzer?.destroy();\n }\n}\n","/** Minimal interface for the built TypstRenderer instance. */\nexport interface RendererInstance {\n free(): void;\n create_session(): RendererSession;\n manipulate_data(\n session: RendererSession,\n action: string,\n data: Uint8Array,\n ): void;\n svg_data(session: RendererSession): string;\n}\n\n/** Minimal interface for a TypstRenderer session. */\nexport interface RendererSession {\n free(): void;\n}\n\ntype RendererWasmModule = typeof import(\"@myriaddreamin/typst-ts-renderer\");\n\ndeclare const __TYPST_TS_RENDERER_VERSION__: string;\n\nconst DEFAULT_RENDERER_WASM_URL = `https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-renderer@${__TYPST_TS_RENDERER_VERSION__}/pkg/typst_ts_renderer_bg.wasm`;\n\nlet rendererModulePromise: Promise<RendererWasmModule> | null = null;\n\nfunction getRendererModule(): Promise<RendererWasmModule> {\n if (!rendererModulePromise) {\n rendererModulePromise = import(\"@myriaddreamin/typst-ts-renderer\").catch(\n (err) => {\n rendererModulePromise = null;\n throw err;\n },\n );\n }\n return rendererModulePromise;\n}\n\nexport interface TypstRendererOptions {\n /** URL to the typst-ts-renderer WASM binary. Defaults to jsDelivr CDN. */\n wasmUrl?: string;\n}\n\nexport interface RenderedSvgPage {\n /** Zero-based page index within the document. */\n index: number;\n /** Page width in typographic points. */\n width: number;\n /** Page height in typographic points. */\n height: number;\n /** Standalone SVG string for just this page. */\n svg: string;\n}\n\n/**\n * Converts Typst vector artifacts to SVG strings.\n *\n * The renderer WASM module is loaded lazily on first use.\n *\n * const renderer = TypstRenderer.create();\n * const svg = await renderer.renderSvg(vector);\n */\nexport class TypstRenderer {\n private wasmUrl: string;\n private instance: Promise<RendererInstance> | null = null;\n\n private constructor(options: TypstRendererOptions = {}) {\n this.wasmUrl = options.wasmUrl ?? DEFAULT_RENDERER_WASM_URL;\n // Eagerly start loading the WASM module so it's ready by first use.\n getRendererModule().catch(() => {});\n }\n\n static create(options: TypstRendererOptions = {}): TypstRenderer {\n return new TypstRenderer(options);\n }\n\n private getInstance(): Promise<RendererInstance> {\n if (!this.instance) {\n this.instance = this.#init().catch((err) => {\n this.instance = null;\n throw err;\n });\n }\n return this.instance;\n }\n\n async #init(): Promise<RendererInstance> {\n const mod = await getRendererModule();\n await mod.default({ module_or_path: this.wasmUrl });\n return new mod.TypstRendererBuilder().build();\n }\n\n /** Free the underlying WASM renderer instance. */\n async destroy(): Promise<void> {\n const instance = this.instance;\n this.instance = null;\n if (instance) {\n (await instance).free();\n }\n }\n\n /** Render a Typst vector artifact to an SVG string. */\n async renderSvg(vector: Uint8Array): Promise<string> {\n const renderer = await this.getInstance();\n const session = renderer.create_session();\n try {\n renderer.manipulate_data(session, \"reset\", vector);\n return renderer.svg_data(session);\n } finally {\n session.free();\n }\n }\n\n /**\n * Render a Typst vector artifact into one self-contained SVG string per\n * physical page. The merged SVG is split by `<g class=\"typst-page\">`\n * children; each group's `data-page-width` / `data-page-height` give the\n * page-local viewBox. Shared `<defs>` / `<style>` are duplicated into each\n * page so the output SVGs render independently. Returns an empty array if\n * the document has no page groups.\n */\n async renderSvgPages(vector: Uint8Array): Promise<RenderedSvgPage[]> {\n return splitMergedSvgPages(await this.renderSvg(vector));\n }\n}\n\n// Parsing must use \"text/html\", not \"image/svg+xml\": Typst's merged SVG\n// output has repeatedly failed XML-strict parsing. HTML mode tolerates it\n// and still produces real SVGSVGElement nodes for inline SVG.\nfunction splitMergedSvgPages(svg: string): RenderedSvgPage[] {\n const doc = new DOMParser().parseFromString(svg, \"text/html\");\n const root = doc.querySelector(\"svg\");\n if (!root) return [];\n\n const children = Array.from(root.children);\n const pageGroups = children.filter(\n (el) =>\n el.tagName.toLowerCase() === \"g\" && el.classList.contains(\"typst-page\"),\n );\n if (pageGroups.length === 0) return [];\n\n const sharedHtml = children\n .filter((el) => !el.classList.contains(\"typst-page\"))\n .map((el) => el.outerHTML)\n .join(\"\");\n\n const namespaceAttrs = Array.from(root.attributes)\n .filter((attr) => attr.name === \"xmlns\" || attr.name.startsWith(\"xmlns:\"))\n .map((attr) => `${attr.name}=\"${attr.value}\"`)\n .join(\" \");\n\n return pageGroups.flatMap((group, index) => {\n const width = Number(group.getAttribute(\"data-page-width\")) || 0;\n const height = Number(group.getAttribute(\"data-page-height\")) || 0;\n if (width <= 0 || height <= 0) return [];\n\n const clone = group.cloneNode(true) as Element;\n clone.removeAttribute(\"transform\");\n\n return [\n {\n index,\n width,\n height,\n svg:\n `<svg ${namespaceAttrs} viewBox=\"0 0 ${width} ${height}\" ` +\n `width=\"${width}\" height=\"${height}\">` +\n `${sharedHtml}${clone.outerHTML}</svg>`,\n },\n ];\n });\n}\n"],"mappings":"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","names":["Comlink"]}
|
|
1
|
+
{"version":3,"sources":["../src/analyzer.ts","../src/rpc.ts","../src/identifiers.ts","../src/compiler.ts","../src/formatter.ts","../src/compile-scheduler.ts","../src/project.ts","../src/renderer.ts"],"sourcesContent":["import * as Comlink from \"comlink\";\nimport type {\n LspCompletionResponse,\n LspHover,\n LspPosition,\n} from \"./analyzer-types.js\";\nimport type { AnalyzerWorker } from \"./analyzer-worker.js\";\nimport { createAnalyzerWorker } from \"./rpc.js\";\n\nexport interface TypstAnalyzerOptions {\n /**\n * Explicit Worker instance. When omitted, an inlined blob worker is created automatically.\n * Use this for Vite apps:\n * `await TypstAnalyzer.create({ worker: new Worker(new URL('typst-web-service/analyzer-worker', import.meta.url), { type: 'module' }) })`\n */\n worker?: Worker;\n /**\n * URL to the tinymist WASM binary.\n * Required — there is no default CDN URL for tinymist-web.\n */\n wasmUrl: string;\n}\n\n/**\n * Manages a tinymist language server in a Web Worker. Provides LSP-based\n * completion and hover for Typst documents.\n *\n * const analyzer = await TypstAnalyzer.create({ wasmUrl: '...' });\n */\nexport class TypstAnalyzer {\n private readonly proxy: Comlink.Remote<AnalyzerWorker>;\n private readonly worker: Worker;\n private versionCounter = 0;\n /**\n * Last content pushed to the worker per URI. Presence is the source of\n * truth for \"is this URI opened on the worker?\"; value drives own-RPC dedup.\n */\n private readonly content = new Map<string, string>();\n\n private constructor(worker: Worker, proxy: Comlink.Remote<AnalyzerWorker>) {\n this.worker = worker;\n this.proxy = proxy;\n }\n\n static async create(options: TypstAnalyzerOptions): Promise<TypstAnalyzer> {\n const worker = options.worker ?? createAnalyzerWorker();\n const proxy = Comlink.wrap<AnalyzerWorker>(worker);\n const absoluteWasmUrl = new URL(options.wasmUrl, globalThis.location?.href)\n .href;\n\n const analyzer = new TypstAnalyzer(worker, proxy);\n\n await proxy.init(absoluteWasmUrl);\n\n return analyzer;\n }\n\n async didOpen(uri: string, content: string): Promise<void> {\n this.content.set(uri, content);\n await this.proxy.didOpen(uri, content);\n }\n\n async didClose(uri: string): Promise<void> {\n if (!this.content.delete(uri)) return;\n await this.proxy.didClose(uri);\n }\n\n /**\n * Notify the analyzer that a document has changed. Skips the RPC when the\n * content matches what the worker last saw.\n */\n async didChange(uri: string, content: string): Promise<void> {\n if (!this.content.has(uri)) {\n await this.didOpen(uri, content);\n return;\n }\n if (this.content.get(uri) === content) return;\n this.content.set(uri, content);\n const version = ++this.versionCounter;\n await this.proxy.didChange(uri, version, content);\n }\n\n /**\n * Batch document changes. Splits inputs into opens (first-time URIs) and\n * changes (already-open URIs) and sends them in a single worker roundtrip.\n * Skips unchanged documents; returns without an RPC if nothing is pending.\n */\n async didChangeMany(docs: Record<string, string>): Promise<void> {\n const opens: Array<{ uri: string; content: string }> = [];\n const changes: Array<{ uri: string; version: number; content: string }> =\n [];\n for (const [uri, content] of Object.entries(docs)) {\n if (!this.content.has(uri)) {\n opens.push({ uri, content });\n this.content.set(uri, content);\n } else if (this.content.get(uri) !== content) {\n changes.push({ uri, version: ++this.versionCounter, content });\n this.content.set(uri, content);\n }\n }\n if (opens.length === 0 && changes.length === 0) return;\n await this.proxy.didChangeMany(opens, changes);\n }\n\n /**\n * Batch document closes. Filters to currently-open URIs and sends the set\n * in a single worker roundtrip.\n */\n async didCloseMany(uris: string[]): Promise<void> {\n const toClose: string[] = [];\n for (const uri of uris) {\n if (this.content.delete(uri)) toClose.push(uri);\n }\n if (toClose.length === 0) return;\n await this.proxy.didCloseMany(toClose);\n }\n\n /**\n * Request completion at `position` for `uri`, with `content` as the current\n * document state. Bundles the didChange notification with the request in one\n * worker roundtrip; degrades to a plain completion request when the worker\n * already has this exact content.\n */\n async completion(\n uri: string,\n content: string,\n position: LspPosition,\n ): Promise<LspCompletionResponse> {\n if (this.content.get(uri) === content) {\n return this.proxy.completion(uri, position);\n }\n const isOpen = this.content.has(uri);\n this.content.set(uri, content);\n const version = ++this.versionCounter;\n return this.proxy.completionWithDoc(\n uri,\n version,\n content,\n position,\n isOpen ? \"change\" : \"open\",\n );\n }\n\n /**\n * Request hover at `position` for `uri`, with `content` as the current\n * document state. Bundles the didChange notification with the request in one\n * worker roundtrip; degrades to a plain hover request when the worker\n * already has this exact content.\n */\n async hover(\n uri: string,\n content: string,\n position: LspPosition,\n ): Promise<LspHover | null> {\n if (this.content.get(uri) === content) {\n return this.proxy.hover(uri, position);\n }\n const isOpen = this.content.has(uri);\n this.content.set(uri, content);\n const version = ++this.versionCounter;\n return this.proxy.hoverWithDoc(\n uri,\n version,\n content,\n position,\n isOpen ? \"change\" : \"open\",\n );\n }\n\n destroy(): void {\n this.proxy[Comlink.releaseProxy]();\n this.worker.terminate();\n }\n}\n","// Injected at build time by tsup (see tsup.config.ts)\ndeclare const __WORKER_CODE__: string;\ndeclare const __ANALYZER_WORKER_CODE__: string;\n\n/** Create a Worker from an inlined code string, auto-revoking the blob URL on terminate. */\nfunction createBlobWorker(code: string): Worker {\n const blob = new Blob([code], { type: \"application/javascript\" });\n const url = URL.createObjectURL(blob);\n const worker = new Worker(url);\n const origTerminate = worker.terminate.bind(worker);\n worker.terminate = () => {\n origTerminate();\n URL.revokeObjectURL(url);\n };\n return worker;\n}\n\n/** Create a blob Worker from the inlined compiler worker code. */\nexport function createWorker(): Worker {\n return createBlobWorker(__WORKER_CODE__);\n}\n\n/** Create a blob Worker from the inlined analyzer worker code. */\nexport function createAnalyzerWorker(): Worker {\n return createBlobWorker(__ANALYZER_WORKER_CODE__);\n}\n","/**\n * Two addressing schemes live in this codebase. This file is the only place\n * that knows how they relate. Keeping the vocabulary and conversions colocated\n * means a new contributor can read one file and understand the model.\n *\n * 1. Path — \"/main.typ\". Always leading-slash, always forward slashes.\n * Used by the compiler VFS, the `TypstProject` public API,\n * and the `typstFilePath` facet. Addresses a file within\n * the project.\n *\n * 2. AnalyzerUri — \"untitled:project/main.typ\". What tinymist's LSP expects.\n * Derived from a Path plus the analyzer URI root.\n *\n * The types below are type aliases, not branded/opaque types. That's\n * deliberate: callers can pass string literals where a Path is expected\n * without wrapping, and the aliases only serve as self-documenting\n * signatures. Ingress points still need to call `normalizePath` to defend\n * against un-normalized input — the alias does not imply the string has\n * been normalized.\n */\n\n/** `/path/to/file.typ` — leading-slash, forward slashes only. */\nexport type Path = string;\n\n/** `untitled:project/path/to/file.typ` — what tinymist's LSP consumes. */\nexport type AnalyzerUri = string;\n\n/** Ensure a path starts with a leading slash. Idempotent. */\nexport function normalizePath(path: string): Path {\n return path.startsWith(\"/\") ? path : `/${path}`;\n}\n\n/**\n * Normalize an analyzer URI root. Ensures leading slash, strips trailing\n * slashes. Special-cases \"/\" → \"\" so URIs don't end up with a leading\n * `untitled://`.\n */\nexport function normalizeRoot(rootPath: string): string {\n const root = normalizePath(rootPath);\n return root === \"/\" ? \"\" : root.replace(/\\/+$/, \"\");\n}\n\n/**\n * Build the analyzer URI for a given project path. `root` is expected to\n * already be normalized (see `normalizeRoot`).\n *\n * pathToAnalyzerUri(\"/main.typ\", \"/project\") -> \"untitled:project/main.typ\"\n */\nexport function pathToAnalyzerUri(path: Path, root: string): AnalyzerUri {\n const bare = root.replace(/^\\//, \"\");\n return `untitled:${bare}${normalizePath(path)}`;\n}\n","import * as Comlink from \"comlink\";\nimport { createWorker } from \"./rpc.js\";\nimport type { DiagnosticMessage } from \"./types.js\";\nimport type { CompilerWorker } from \"./compiler-worker.js\";\n\ndeclare const __TYPST_TS_WEB_COMPILER_VERSION__: string;\n\nexport interface CompileResult {\n diagnostics: DiagnosticMessage[];\n /** Vector artifact bytes from the compiler, usable with TypstRenderer for SVG rendering. */\n vector?: Uint8Array;\n}\n\nexport interface TypstCompilerOptions {\n /**\n * Explicit Worker instance. When omitted, an inlined blob worker is created automatically.\n * Use this for Vite apps to get proper source maps:\n * `await TypstCompiler.create({ worker: new Worker(new URL('typst-web-service/compiler-worker', import.meta.url)) })`\n */\n worker?: Worker;\n /**\n * URL to the typst-ts-web-compiler WASM binary.\n * Defaults to the matching version on jsDelivr CDN.\n * Override with a local asset URL for offline support or faster load:\n * `new URL('@myriaddreamin/typst-ts-web-compiler/pkg/typst_ts_web_compiler_bg.wasm', import.meta.url).href`\n */\n wasmUrl?: string;\n /** Font URLs to load into the Typst compiler. Defaults to Roboto from jsDelivr. */\n fonts?: string[];\n /**\n * Enable fetching @preview/ packages from packages.typst.org on demand.\n * Default: true.\n */\n packages?: boolean;\n}\n\nconst DEFAULT_FONTS = [\n \"https://cdn.jsdelivr.net/npm/roboto-font@0.1.0/fonts/Roboto/roboto-regular-webfont.ttf\",\n];\n\nconst DEFAULT_WASM_URL = `https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-web-compiler@${__TYPST_TS_WEB_COMPILER_VERSION__}/pkg/typst_ts_web_compiler_bg.wasm`;\n\n/**\n * Manages a Typst compiler worker. Create one instance and share it across\n * all extensions (linter, autocomplete, preview, etc.).\n *\n * await TypstCompiler.create() // blob worker, defaults\n * await TypstCompiler.create({ wasmUrl: '...' }) // blob worker, custom WASM\n * await TypstCompiler.create({ worker: myWorker }) // explicit Worker (Vite)\n * await TypstCompiler.create({ worker: myWorker, fonts: [...] }) // explicit Worker + options\n */\nexport class TypstCompiler {\n private readonly proxy: Comlink.Remote<CompilerWorker>;\n private readonly worker: Worker;\n private readonly encoder = new TextEncoder();\n /** Last text content pushed per path. Drives own-RPC dedup. Invalidated by binary writes. */\n private readonly content = new Map<string, string>();\n\n private constructor(worker: Worker, proxy: Comlink.Remote<CompilerWorker>) {\n this.worker = worker;\n this.proxy = proxy;\n }\n\n static async create(\n options: TypstCompilerOptions = {},\n ): Promise<TypstCompiler> {\n const worker = options.worker ?? createWorker();\n const proxy = Comlink.wrap<CompilerWorker>(worker);\n\n await proxy.init(\n options.wasmUrl ?? DEFAULT_WASM_URL,\n options.fonts ?? DEFAULT_FONTS,\n options.packages ?? true,\n );\n\n return new TypstCompiler(worker, proxy);\n }\n\n /**\n * Compile whatever is currently in the VFS (populated via\n * setText/setBinary/setJson/setMany). Defaults to compiling \"/main.typ\";\n * override with `entry`.\n */\n compile(entry?: string): Promise<CompileResult> {\n return this.proxy.compile(entry);\n }\n\n /**\n * Compile to PDF. Operates on whatever is currently in the VFS (populated\n * via setText/setBinary/setJson/setMany). Defaults to compiling \"/main.typ\";\n * override with `entry`.\n */\n compilePdf(entry?: string): Promise<Uint8Array> {\n return this.proxy.compilePdf(entry);\n }\n\n /**\n * Add or overwrite a text file in the virtual compiler filesystem. Skips\n * the worker RPC when `source` matches the last value pushed for `path`.\n */\n async setText(path: string, source: string): Promise<void> {\n if (this.content.get(path) === source) return;\n this.content.set(path, source);\n return this.proxy.mapShadow(path, this.encoder.encode(source));\n }\n\n /** Add or overwrite a JSON file in the virtual compiler filesystem. */\n setJson(\n path: string,\n value: unknown,\n replacer?: (this: unknown, key: string, value: unknown) => unknown,\n space?: string | number,\n ): Promise<void> {\n return this.setText(path, JSON.stringify(value, replacer, space));\n }\n\n /**\n * Add or overwrite multiple files in the virtual compiler filesystem in a\n * single worker roundtrip. Strings are UTF-8 encoded; Uint8Arrays are\n * passed through. Text entries unchanged since their last push are skipped;\n * binary entries always push and invalidate the text cache for their path.\n */\n async setMany(files: Record<string, string | Uint8Array>): Promise<void> {\n const encoded: Record<string, Uint8Array> = {};\n for (const [path, content] of Object.entries(files)) {\n if (typeof content === \"string\") {\n if (this.content.get(path) === content) continue;\n this.content.set(path, content);\n encoded[path] = this.encoder.encode(content);\n } else {\n this.content.delete(path);\n encoded[path] = content;\n }\n }\n if (Object.keys(encoded).length === 0) return;\n return this.proxy.mapShadowMany(encoded);\n }\n\n /** Add or overwrite a binary file in the virtual compiler filesystem. */\n setBinary(\n path: string,\n content: ArrayBuffer | ArrayBufferView,\n ): Promise<void> {\n this.content.delete(path);\n const bytes =\n content instanceof ArrayBuffer\n ? new Uint8Array(content)\n : new Uint8Array(\n content.buffer,\n content.byteOffset,\n content.byteLength,\n );\n return this.proxy.mapShadow(path, bytes);\n }\n\n /** Remove a file from the virtual compiler filesystem. */\n remove(path: string): Promise<void> {\n this.content.delete(path);\n return this.proxy.unmapShadow(path);\n }\n\n /** Clear all virtual files from the compiler filesystem. */\n clear(): Promise<void> {\n this.content.clear();\n return this.proxy.resetShadow();\n }\n\n destroy(): void {\n this.proxy[Comlink.releaseProxy]();\n this.worker.terminate();\n }\n}\n","export interface FormatConfig {\n /** Number of spaces per indentation level. Default: 2 */\n tab_spaces?: number;\n /** Maximum line width. Default: 80 */\n max_width?: number;\n /** Maximum consecutive blank lines allowed. */\n blank_lines_upper_bound?: number;\n /** Collapse consecutive whitespace in markup to a single space. */\n collapse_markup_spaces?: boolean;\n /** Sort import items alphabetically. */\n reorder_import_items?: boolean;\n /** Wrap text in markup to fit within max_width. Implies collapse_markup_spaces. */\n wrap_text?: boolean;\n}\n\nexport interface FormatRangeResult {\n /** Start index (UTF-16) of the actual formatted range. */\n start: number;\n /** End index (UTF-16) of the actual formatted range. */\n end: number;\n /** The formatted text for the range. */\n text: string;\n}\n\ntype TypstyleModule = typeof import(\"@typstyle/typstyle-wasm-bundler\");\n\nlet typstylePromise: Promise<TypstyleModule> | null = null;\n\nfunction getTypstyle(): Promise<TypstyleModule> {\n if (!typstylePromise) {\n typstylePromise = import(\"@typstyle/typstyle-wasm-bundler\").catch((err) => {\n typstylePromise = null;\n throw err;\n });\n }\n return typstylePromise;\n}\n\n/**\n * Typst code formatter powered by typstyle.\n *\n * Runs on the main thread — typstyle is lightweight and fast.\n * The WASM module is loaded lazily on first format call.\n * Requires a bundler that supports WASM imports (e.g. Vite, webpack).\n *\n * const formatter = TypstFormatter.create({ tab_spaces: 2, max_width: 80 });\n * const formatted = await formatter.format(source);\n */\nexport class TypstFormatter {\n private config: FormatConfig;\n\n private constructor(config: FormatConfig = {}) {\n this.config = config;\n // Eagerly start loading WASM so it's ready by first use.\n // Swallow preload errors — they'll surface on first format() call.\n getTypstyle().catch(() => {});\n }\n\n static create(config: FormatConfig = {}): TypstFormatter {\n return new TypstFormatter(config);\n }\n\n /** Format an entire Typst source string. */\n async format(source: string): Promise<string> {\n const typstyle = await getTypstyle();\n return typstyle.format(source, this.config);\n }\n\n /** Format a range within a Typst source string. Indices are UTF-16 code units. */\n async formatRange(\n source: string,\n start: number,\n end: number,\n ): Promise<FormatRangeResult> {\n const typstyle = await getTypstyle();\n const result = typstyle.format_range(source, start, end, this.config);\n return { start: result.start, end: result.end, text: result.text };\n }\n}\n","interface CompileSchedulerOptions {\n /** Minimum idle time (ms) after the last request before firing. Default: 0. */\n debounceMs?: number;\n /**\n * Maximum time (ms) the debounce may keep deferring during continuous\n * requests. Guarantees a fire at least this often so users see progress\n * while typing. Default: 0 (no cap).\n */\n maxWaitMs?: number;\n}\n\n/**\n * Debounce helper with a max-wait ceiling for coalescing compile requests. A\n * burst of `schedule(cb)` calls within `debounceMs` collapses into one fire;\n * during sustained bursts, `maxWaitMs` caps how long the debounce may keep\n * deferring.\n */\nexport class CompileScheduler {\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private maxWaitTimer: ReturnType<typeof setTimeout> | null = null;\n private lastFireTime = 0;\n\n constructor(private readonly options: CompileSchedulerOptions = {}) {}\n\n schedule(callback: () => void): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n const delay = Math.max(0, this.options.debounceMs ?? 0);\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.fire(callback);\n }, delay);\n\n const maxWait = this.options.maxWaitMs;\n if (maxWait != null && maxWait > 0 && !this.maxWaitTimer) {\n const wait = Math.max(\n 0,\n maxWait - (performance.now() - this.lastFireTime),\n );\n this.maxWaitTimer = setTimeout(() => {\n this.maxWaitTimer = null;\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n this.fire(callback);\n }\n }, wait);\n }\n }\n\n /** Cancel any pending scheduled fire without calling the callback. */\n cancel(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n if (this.maxWaitTimer) {\n clearTimeout(this.maxWaitTimer);\n this.maxWaitTimer = null;\n }\n }\n\n private fire(callback: () => void): void {\n this.lastFireTime = performance.now();\n callback();\n }\n}\n","import type { TypstAnalyzer } from \"./analyzer.js\";\nimport type {\n LspCompletionResponse,\n LspHover,\n LspPosition,\n} from \"./analyzer-types.js\";\nimport { CompileScheduler } from \"./compile-scheduler.js\";\nimport type { CompileResult, TypstCompiler } from \"./compiler.js\";\nimport {\n normalizePath,\n normalizeRoot,\n type Path,\n pathToAnalyzerUri,\n} from \"./identifiers.js\";\n\nexport interface TypstProjectOptions {\n compiler: TypstCompiler;\n /**\n * Optional analyzer. When provided, text file operations also sync with the\n * analyzer so completions / hover reflect the current state.\n */\n analyzer?: TypstAnalyzer;\n /** Default entry file path. Default: \"/main.typ\". */\n entry?: string;\n /**\n * Prefix used to build the `untitled:` URIs handed to the analyzer.\n * Default: \"/project\". A path of `/main.typ` becomes\n * `untitled:project/main.typ`. Only affects URI construction — the compiler\n * and project VFS use the raw paths unchanged.\n */\n analyzerUriRoot?: string;\n /**\n * Scheduling for auto-compiles after VFS mutations. Mutations debounce by\n * `debounceMs`; `maxWaitMs` caps how long the debounce can keep deferring\n * during sustained edits so the user still sees progress.\n */\n autoCompile?: AutoCompileOptions;\n}\n\nexport interface AutoCompileOptions {\n /**\n * Idle time (ms) after the last VFS mutation before a compile fires.\n * Default: 0 — compile fires on the next macrotask. Set higher (e.g. 150) to\n * coalesce rapid edits.\n */\n debounceMs?: number;\n /**\n * Maximum time (ms) the debounce is allowed to defer a compile during\n * sustained mutation bursts. Default: 0 (no cap — pure debounce).\n */\n maxWaitMs?: number;\n}\n\nconst DEFAULT_ENTRY = \"/main.typ\";\nconst DEFAULT_ROOT = \"/project\";\n\n/**\n * Coordinates a compiler + analyzer pair for multi-file Typst projects.\n *\n * Owns the project's virtual filesystem state. Editors push incremental\n * `setText` updates as the user types; the project mirrors those edits to\n * both the compiler's shadow VFS and the analyzer's open-document set, then\n * compiles or services LSP requests against the current state.\n *\n * const project = new TypstProject({ compiler, analyzer });\n * await project.setMany({ \"/main.typ\": \"...\", \"/utils.typ\": \"...\" });\n * const result = await project.compile();\n */\nexport type CompileListener = (result: CompileResult) => void;\n\nfunction errorAsCompileResult(\n err: unknown,\n paths: readonly string[],\n): CompileResult {\n const message = err instanceof Error ? err.message : String(err);\n return {\n diagnostics: paths.map((path) => ({\n package: \"\",\n path,\n severity: \"Error\",\n range: { startLine: 0, startCol: 0, endLine: 0, endCol: 1 },\n message,\n })),\n };\n}\n\nexport class TypstProject {\n private readonly compiler: TypstCompiler;\n private readonly analyzer?: TypstAnalyzer;\n private readonly analyzerUriRoot: string;\n /**\n * Tracked text files: path → latest content observed. Presence in this map\n * is the source of truth for \"is this a tracked text file?\"; insertion\n * order drives the `files` getter. Per-sink dedup lives in the compiler and\n * analyzer.\n */\n private readonly contentByPath = new Map<Path, string>();\n private readonly compileListeners = new Set<CompileListener>();\n private readonly scheduler: CompileScheduler;\n private compileVersion = 0;\n private _lastResult: CompileResult | undefined;\n private _entry: Path;\n private destroyed = false;\n\n private invokeListener(\n listener: CompileListener,\n result: CompileResult,\n ): void {\n try {\n listener(result);\n } catch (err) {\n console.error(\"[typst] compile listener threw:\", err);\n }\n }\n\n constructor(options: TypstProjectOptions) {\n this.compiler = options.compiler;\n this.analyzer = options.analyzer;\n this.analyzerUriRoot = normalizeRoot(\n options.analyzerUriRoot ?? DEFAULT_ROOT,\n );\n this._entry = normalizePath(options.entry ?? DEFAULT_ENTRY);\n this.scheduler = new CompileScheduler({\n debounceMs: options.autoCompile?.debounceMs,\n maxWaitMs: options.autoCompile?.maxWaitMs,\n });\n }\n\n /**\n * Schedule an auto-compile after VFS mutations. Coalesces rapid calls via\n * the configured debounce/throttle. Errors surface through `onCompile`\n * listeners via a synthetic diagnostic; callers awaiting a specific compile\n * should call `compile()` directly.\n */\n private scheduleCompile(): void {\n if (this.destroyed) return;\n this.scheduler.schedule(() => {\n this.compile().catch((err) => console.error(\"[typst]\", err));\n });\n }\n\n /** Current entry file path. Assign to change the sticky entry used by subsequent `compile()` calls. */\n get entry(): Path {\n return this._entry;\n }\n\n set entry(path: Path) {\n const next = normalizePath(path);\n if (next === this._entry) return;\n this._entry = next;\n this.scheduleCompile();\n }\n\n /** Whether an analyzer is attached. */\n get hasAnalyzer(): boolean {\n return this.analyzer !== undefined;\n }\n\n /**\n * Most recent compile result, or `undefined` before the first compile has\n * settled. Useful for lazy-mounted UI that subscribes after boot and needs\n * an initial value.\n */\n get lastResult(): CompileResult | undefined {\n return this._lastResult;\n }\n\n /**\n * Snapshot of tracked text file paths, in insertion order. Updated by\n * `setText`, `setMany`, `remove`, and `clear`. Returns a fresh array — mutate\n * freely without affecting project state.\n */\n get files(): Path[] {\n return [...this.contentByPath.keys()];\n }\n\n /**\n * Current text content for a tracked file, or `undefined` if the path was\n * never written via `setText`/`setMany` (or was removed). Read-through to the\n * project's sync cache — lets consumers avoid shadowing the VFS themselves.\n */\n getText(path: Path): string | undefined {\n return this.contentByPath.get(normalizePath(path));\n }\n\n /**\n * Add or overwrite a text file. Goes to the compiler's VFS and, when an\n * analyzer is attached, to the analyzer as a document change. No-op when\n * the tracked path already has this exact content — skips both worker RPCs\n * and the auto-scheduled compile.\n */\n async setText(path: Path, content: string): Promise<void> {\n const p = normalizePath(path);\n if (this.contentByPath.get(p) === content) return;\n this.contentByPath.set(p, content);\n await Promise.all([\n this.compiler.setText(p, content),\n this.analyzer?.didChange(\n pathToAnalyzerUri(p, this.analyzerUriRoot),\n content,\n ) ?? Promise.resolve(),\n ]);\n this.scheduleCompile();\n }\n\n /**\n * Add or overwrite a JSON file. Compiler-only — the analyzer does not track\n * data files.\n */\n async setJson(path: Path, value: unknown): Promise<void> {\n await this.compiler.setJson(normalizePath(path), value);\n this.scheduleCompile();\n }\n\n /** Add or overwrite a binary file. Compiler-only. */\n async setBinary(\n path: Path,\n content: ArrayBuffer | ArrayBufferView,\n ): Promise<void> {\n await this.compiler.setBinary(normalizePath(path), content);\n this.scheduleCompile();\n }\n\n /**\n * Batch set multiple files. Strings route to both compiler and analyzer;\n * Uint8Array entries go to the compiler only. Strings matching the last\n * tracked content for their path are skipped on both sinks. Binary entries\n * always go through (no content cache, so no dedup).\n */\n async setMany(files: Record<Path, string | Uint8Array>): Promise<void> {\n const normalized: Record<Path, string | Uint8Array> = {};\n const analyzerDocs: Record<string, string> = {};\n for (const [path, content] of Object.entries(files)) {\n const p = normalizePath(path);\n if (typeof content !== \"string\") {\n normalized[p] = content;\n continue;\n }\n if (this.contentByPath.get(p) === content) continue;\n this.contentByPath.set(p, content);\n normalized[p] = content;\n analyzerDocs[pathToAnalyzerUri(p, this.analyzerUriRoot)] = content;\n }\n if (Object.keys(normalized).length === 0) return;\n await Promise.all([\n this.compiler.setMany(normalized),\n this.analyzer?.didChangeMany(analyzerDocs) ?? Promise.resolve(),\n ]);\n this.scheduleCompile();\n }\n\n /**\n * Remove a file. Always removed from the compiler's VFS; also closed on the\n * analyzer when it was previously tracked as text.\n */\n async remove(path: Path): Promise<void> {\n const p = normalizePath(path);\n const wasText = this.contentByPath.delete(p);\n await Promise.all([\n this.compiler.remove(p),\n wasText\n ? this.analyzer?.didClose(pathToAnalyzerUri(p, this.analyzerUriRoot))\n : undefined,\n ]);\n this.scheduleCompile();\n }\n\n /** Clear all files from both compiler VFS and analyzer document set. */\n async clear(): Promise<void> {\n const uris = Array.from(this.contentByPath.keys(), (p) =>\n pathToAnalyzerUri(p, this.analyzerUriRoot),\n );\n this.contentByPath.clear();\n await Promise.all([\n this.compiler.clear(),\n uris.length > 0 ? this.analyzer?.didCloseMany(uris) : undefined,\n ]);\n this.scheduleCompile();\n }\n\n /**\n * Subscribe to compile results. Fires after every `compile()` whose result is\n * still current (stale results from out-of-order concurrent compiles are\n * dropped). If a compile has already settled, the most recent result is\n * delivered synchronously so late-mounted listeners aren't stuck blank until\n * the next compile. Returns an unsubscribe function.\n */\n onCompile(listener: CompileListener): () => void {\n this.compileListeners.add(listener);\n if (this._lastResult !== undefined) {\n this.invokeListener(listener, this._lastResult);\n }\n return () => {\n this.compileListeners.delete(listener);\n };\n }\n\n /**\n * Compile the current VFS state using the sticky entry. Errors from the\n * underlying compiler are converted into a synthetic error diagnostic so\n * callers and listeners always receive a `CompileResult`. Listeners are\n * notified only for the most recent compile — results from an earlier call\n * that resolves after a later one are suppressed.\n *\n * VFS mutations (`setText`, `remove`, etc.) auto-schedule a debounced\n * compile; call this directly only when you need an awaitable handle on the\n * result (e.g., to flush before rendering to PDF).\n */\n async compile(): Promise<CompileResult> {\n this.scheduler.cancel();\n const version = ++this.compileVersion;\n let result: CompileResult;\n try {\n result = await this.compiler.compile(this._entry);\n } catch (err) {\n // Spread the synthetic error across every tracked text path so the\n // diagnostic is visible no matter which file the user is viewing.\n // Falls back to the entry if nothing is tracked yet.\n const paths =\n this.contentByPath.size > 0\n ? [...this.contentByPath.keys()]\n : [this._entry];\n result = errorAsCompileResult(err, paths);\n }\n if (version === this.compileVersion) {\n this._lastResult = result;\n for (const listener of this.compileListeners) {\n this.invokeListener(listener, result);\n }\n }\n return result;\n }\n\n /** Compile the current VFS state to PDF using the sticky entry. */\n compilePdf(): Promise<Uint8Array> {\n return this.compiler.compilePdf(this._entry);\n }\n\n private requireAnalyzer(operation: string): TypstAnalyzer {\n if (!this.analyzer) {\n throw new Error(`TypstProject: ${operation} requires an analyzer`);\n }\n return this.analyzer;\n }\n\n /**\n * Request completion for `path` at `position`, using `source` as the\n * current document state. One analyzer roundtrip; compiler is not touched —\n * the compile sync path writes to the compiler separately. Throws when no\n * analyzer is attached.\n */\n completion(\n path: Path,\n source: string,\n position: LspPosition,\n ): Promise<LspCompletionResponse> {\n const analyzer = this.requireAnalyzer(\"completion\");\n const p = normalizePath(path);\n this.contentByPath.set(p, source);\n return analyzer.completion(\n pathToAnalyzerUri(p, this.analyzerUriRoot),\n source,\n position,\n );\n }\n\n /**\n * Request hover for `path` at `position`, using `source` as the current\n * document state. One analyzer roundtrip; compiler is not touched. Throws\n * when no analyzer is attached.\n */\n hover(\n path: Path,\n source: string,\n position: LspPosition,\n ): Promise<LspHover | null> {\n const analyzer = this.requireAnalyzer(\"hover\");\n const p = normalizePath(path);\n this.contentByPath.set(p, source);\n return analyzer.hover(\n pathToAnalyzerUri(p, this.analyzerUriRoot),\n source,\n position,\n );\n }\n\n /**\n * Tear down the project and the services it owns. Destroys the attached\n * compiler and analyzer, drops all listeners, and clears VFS tracking state.\n * Idempotent — calling twice is a no-op. After destruction, further calls on\n * the project are not supported; construct a new one.\n *\n * If you need to share a compiler or analyzer across projects, destroy them\n * yourself and don't call this method — the project does not provide an\n * ownership toggle.\n */\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.scheduler.cancel();\n this.compileListeners.clear();\n this.contentByPath.clear();\n this._lastResult = undefined;\n this.compiler.destroy();\n this.analyzer?.destroy();\n }\n}\n","/** Minimal interface for the built TypstRenderer instance. */\nexport interface RendererInstance {\n free(): void;\n create_session(): RendererSession;\n manipulate_data(\n session: RendererSession,\n action: string,\n data: Uint8Array,\n ): void;\n svg_data(session: RendererSession): string;\n}\n\n/** Minimal interface for a TypstRenderer session. */\nexport interface RendererSession {\n free(): void;\n}\n\ntype RendererWasmModule = typeof import(\"@myriaddreamin/typst-ts-renderer\");\n\ndeclare const __TYPST_TS_RENDERER_VERSION__: string;\n\nconst DEFAULT_RENDERER_WASM_URL = `https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-renderer@${__TYPST_TS_RENDERER_VERSION__}/pkg/typst_ts_renderer_bg.wasm`;\n\nlet rendererModulePromise: Promise<RendererWasmModule> | null = null;\n\nfunction getRendererModule(): Promise<RendererWasmModule> {\n if (!rendererModulePromise) {\n rendererModulePromise = import(\"@myriaddreamin/typst-ts-renderer\").catch(\n (err) => {\n rendererModulePromise = null;\n throw err;\n },\n );\n }\n return rendererModulePromise;\n}\n\nexport interface TypstRendererOptions {\n /** URL to the typst-ts-renderer WASM binary. Defaults to jsDelivr CDN. */\n wasmUrl?: string;\n}\n\nexport interface RenderedSvgPage {\n /** Zero-based page index within the document. */\n index: number;\n /** Page width in typographic points. */\n width: number;\n /** Page height in typographic points. */\n height: number;\n /** Standalone SVG string for just this page. */\n svg: string;\n}\n\n/**\n * Converts Typst vector artifacts to SVG strings.\n *\n * The renderer WASM module is loaded lazily on first use.\n *\n * const renderer = TypstRenderer.create();\n * const svg = await renderer.renderSvg(vector);\n */\nexport class TypstRenderer {\n private wasmUrl: string;\n private instance: Promise<RendererInstance> | null = null;\n\n private constructor(options: TypstRendererOptions = {}) {\n this.wasmUrl = options.wasmUrl ?? DEFAULT_RENDERER_WASM_URL;\n // Eagerly start loading the WASM module so it's ready by first use.\n getRendererModule().catch(() => {});\n }\n\n static create(options: TypstRendererOptions = {}): TypstRenderer {\n return new TypstRenderer(options);\n }\n\n private getInstance(): Promise<RendererInstance> {\n if (!this.instance) {\n this.instance = this.#init().catch((err) => {\n this.instance = null;\n throw err;\n });\n }\n return this.instance;\n }\n\n async #init(): Promise<RendererInstance> {\n const mod = await getRendererModule();\n await mod.default({ module_or_path: this.wasmUrl });\n return new mod.TypstRendererBuilder().build();\n }\n\n /** Free the underlying WASM renderer instance. */\n async destroy(): Promise<void> {\n const instance = this.instance;\n this.instance = null;\n if (instance) {\n (await instance).free();\n }\n }\n\n /** Render a Typst vector artifact to an SVG string. */\n async renderSvg(vector: Uint8Array): Promise<string> {\n const renderer = await this.getInstance();\n const session = renderer.create_session();\n try {\n renderer.manipulate_data(session, \"reset\", vector);\n return renderer.svg_data(session);\n } finally {\n session.free();\n }\n }\n\n /**\n * Render a Typst vector artifact into one self-contained SVG string per\n * physical page. The merged SVG is split by `<g class=\"typst-page\">`\n * children; each group's `data-page-width` / `data-page-height` give the\n * page-local viewBox. Shared `<defs>` / `<style>` are duplicated into each\n * page so the output SVGs render independently. Returns an empty array if\n * the document has no page groups.\n */\n async renderSvgPages(vector: Uint8Array): Promise<RenderedSvgPage[]> {\n return splitMergedSvgPages(await this.renderSvg(vector));\n }\n}\n\n// Parsing must use \"text/html\", not \"image/svg+xml\": Typst's merged SVG\n// output has repeatedly failed XML-strict parsing. HTML mode tolerates it\n// and still produces real SVGSVGElement nodes for inline SVG.\nfunction splitMergedSvgPages(svg: string): RenderedSvgPage[] {\n const doc = new DOMParser().parseFromString(svg, \"text/html\");\n const root = doc.querySelector(\"svg\");\n if (!root) return [];\n\n const children = Array.from(root.children);\n const pageGroups = children.filter(\n (el) =>\n el.tagName.toLowerCase() === \"g\" && el.classList.contains(\"typst-page\"),\n );\n if (pageGroups.length === 0) return [];\n\n const sharedHtml = children\n .filter((el) => !el.classList.contains(\"typst-page\"))\n .map((el) => el.outerHTML)\n .join(\"\");\n\n const namespaceAttrs = Array.from(root.attributes)\n .filter((attr) => attr.name === \"xmlns\" || attr.name.startsWith(\"xmlns:\"))\n .map((attr) => `${attr.name}=\"${attr.value}\"`)\n .join(\" \");\n\n return pageGroups.flatMap((group, index) => {\n const width = Number(group.getAttribute(\"data-page-width\")) || 0;\n const height = Number(group.getAttribute(\"data-page-height\")) || 0;\n if (width <= 0 || height <= 0) return [];\n\n const clone = group.cloneNode(true) as Element;\n clone.removeAttribute(\"transform\");\n\n return [\n {\n index,\n width,\n height,\n svg:\n `<svg ${namespaceAttrs} viewBox=\"0 0 ${width} ${height}\" ` +\n `width=\"${width}\" height=\"${height}\">` +\n `${sharedHtml}${clone.outerHTML}</svg>`,\n },\n ];\n });\n}\n"],"mappings":";AAAA,YAAY,aAAa;;;ACKzB,SAAS,iBAAiB,MAAsB;AAC9C,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAChE,QAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,QAAM,SAAS,IAAI,OAAO,GAAG;AAC7B,QAAM,gBAAgB,OAAO,UAAU,KAAK,MAAM;AAClD,SAAO,YAAY,MAAM;AACvB,kBAAc;AACd,QAAI,gBAAgB,GAAG;AAAA,EACzB;AACA,SAAO;AACT;AAGO,SAAS,eAAuB;AACrC,SAAO,iBAAiB,yutCAAe;AACzC;AAGO,SAAS,uBAA+B;AAC7C,SAAO,iBAAiB,g3oBAAwB;AAClD;;;ADIO,IAAM,gBAAN,MAAM,eAAc;AAAA,EACR;AAAA,EACA;AAAA,EACT,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKR,UAAU,oBAAI,IAAoB;AAAA,EAE3C,YAAY,QAAgB,OAAuC;AACzE,SAAK,SAAS;AACd,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,aAAa,OAAO,SAAuD;AACzE,UAAM,SAAS,QAAQ,UAAU,qBAAqB;AACtD,UAAM,QAAgB,aAAqB,MAAM;AACjD,UAAM,kBAAkB,IAAI,IAAI,QAAQ,SAAS,WAAW,UAAU,IAAI,EACvE;AAEH,UAAM,WAAW,IAAI,eAAc,QAAQ,KAAK;AAEhD,UAAM,MAAM,KAAK,eAAe;AAEhC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,KAAa,SAAgC;AACzD,SAAK,QAAQ,IAAI,KAAK,OAAO;AAC7B,UAAM,KAAK,MAAM,QAAQ,KAAK,OAAO;AAAA,EACvC;AAAA,EAEA,MAAM,SAAS,KAA4B;AACzC,QAAI,CAAC,KAAK,QAAQ,OAAO,GAAG,EAAG;AAC/B,UAAM,KAAK,MAAM,SAAS,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU,KAAa,SAAgC;AAC3D,QAAI,CAAC,KAAK,QAAQ,IAAI,GAAG,GAAG;AAC1B,YAAM,KAAK,QAAQ,KAAK,OAAO;AAC/B;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,IAAI,GAAG,MAAM,QAAS;AACvC,SAAK,QAAQ,IAAI,KAAK,OAAO;AAC7B,UAAM,UAAU,EAAE,KAAK;AACvB,UAAM,KAAK,MAAM,UAAU,KAAK,SAAS,OAAO;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,MAA6C;AAC/D,UAAM,QAAiD,CAAC;AACxD,UAAM,UACJ,CAAC;AACH,eAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,IAAI,GAAG;AACjD,UAAI,CAAC,KAAK,QAAQ,IAAI,GAAG,GAAG;AAC1B,cAAM,KAAK,EAAE,KAAK,QAAQ,CAAC;AAC3B,aAAK,QAAQ,IAAI,KAAK,OAAO;AAAA,MAC/B,WAAW,KAAK,QAAQ,IAAI,GAAG,MAAM,SAAS;AAC5C,gBAAQ,KAAK,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,QAAQ,CAAC;AAC7D,aAAK,QAAQ,IAAI,KAAK,OAAO;AAAA,MAC/B;AAAA,IACF;AACA,QAAI,MAAM,WAAW,KAAK,QAAQ,WAAW,EAAG;AAChD,UAAM,KAAK,MAAM,cAAc,OAAO,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAa,MAA+B;AAChD,UAAM,UAAoB,CAAC;AAC3B,eAAW,OAAO,MAAM;AACtB,UAAI,KAAK,QAAQ,OAAO,GAAG,EAAG,SAAQ,KAAK,GAAG;AAAA,IAChD;AACA,QAAI,QAAQ,WAAW,EAAG;AAC1B,UAAM,KAAK,MAAM,aAAa,OAAO;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WACJ,KACA,SACA,UACgC;AAChC,QAAI,KAAK,QAAQ,IAAI,GAAG,MAAM,SAAS;AACrC,aAAO,KAAK,MAAM,WAAW,KAAK,QAAQ;AAAA,IAC5C;AACA,UAAM,SAAS,KAAK,QAAQ,IAAI,GAAG;AACnC,SAAK,QAAQ,IAAI,KAAK,OAAO;AAC7B,UAAM,UAAU,EAAE,KAAK;AACvB,WAAO,KAAK,MAAM;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,WAAW;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MACJ,KACA,SACA,UAC0B;AAC1B,QAAI,KAAK,QAAQ,IAAI,GAAG,MAAM,SAAS;AACrC,aAAO,KAAK,MAAM,MAAM,KAAK,QAAQ;AAAA,IACvC;AACA,UAAM,SAAS,KAAK,QAAQ,IAAI,GAAG;AACnC,SAAK,QAAQ,IAAI,KAAK,OAAO;AAC7B,UAAM,UAAU,EAAE,KAAK;AACvB,WAAO,KAAK,MAAM;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,WAAW;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,MAAc,oBAAY,EAAE;AACjC,SAAK,OAAO,UAAU;AAAA,EACxB;AACF;;;AEjJO,SAAS,cAAc,MAAoB;AAChD,SAAO,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAC/C;AAOO,SAAS,cAAc,UAA0B;AACtD,QAAM,OAAO,cAAc,QAAQ;AACnC,SAAO,SAAS,MAAM,KAAK,KAAK,QAAQ,QAAQ,EAAE;AACpD;AAQO,SAAS,kBAAkB,MAAY,MAA2B;AACvE,QAAM,OAAO,KAAK,QAAQ,OAAO,EAAE;AACnC,SAAO,YAAY,IAAI,GAAG,cAAc,IAAI,CAAC;AAC/C;;;ACnDA,YAAYA,cAAa;AAoCzB,IAAM,gBAAgB;AAAA,EACpB;AACF;AAEA,IAAM,mBAAmB,qEAAqE,WAAiC;AAWxH,IAAM,gBAAN,MAAM,eAAc;AAAA,EACR;AAAA,EACA;AAAA,EACA,UAAU,IAAI,YAAY;AAAA;AAAA,EAE1B,UAAU,oBAAI,IAAoB;AAAA,EAE3C,YAAY,QAAgB,OAAuC;AACzE,SAAK,SAAS;AACd,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,aAAa,OACX,UAAgC,CAAC,GACT;AACxB,UAAM,SAAS,QAAQ,UAAU,aAAa;AAC9C,UAAM,QAAgB,cAAqB,MAAM;AAEjD,UAAM,MAAM;AAAA,MACV,QAAQ,WAAW;AAAA,MACnB,QAAQ,SAAS;AAAA,MACjB,QAAQ,YAAY;AAAA,IACtB;AAEA,WAAO,IAAI,eAAc,QAAQ,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,OAAwC;AAC9C,WAAO,KAAK,MAAM,QAAQ,KAAK;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,OAAqC;AAC9C,WAAO,KAAK,MAAM,WAAW,KAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ,MAAc,QAA+B;AACzD,QAAI,KAAK,QAAQ,IAAI,IAAI,MAAM,OAAQ;AACvC,SAAK,QAAQ,IAAI,MAAM,MAAM;AAC7B,WAAO,KAAK,MAAM,UAAU,MAAM,KAAK,QAAQ,OAAO,MAAM,CAAC;AAAA,EAC/D;AAAA;AAAA,EAGA,QACE,MACA,OACA,UACA,OACe;AACf,WAAO,KAAK,QAAQ,MAAM,KAAK,UAAU,OAAO,UAAU,KAAK,CAAC;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAQ,OAA2D;AACvE,UAAM,UAAsC,CAAC;AAC7C,eAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,KAAK,GAAG;AACnD,UAAI,OAAO,YAAY,UAAU;AAC/B,YAAI,KAAK,QAAQ,IAAI,IAAI,MAAM,QAAS;AACxC,aAAK,QAAQ,IAAI,MAAM,OAAO;AAC9B,gBAAQ,IAAI,IAAI,KAAK,QAAQ,OAAO,OAAO;AAAA,MAC7C,OAAO;AACL,aAAK,QAAQ,OAAO,IAAI;AACxB,gBAAQ,IAAI,IAAI;AAAA,MAClB;AAAA,IACF;AACA,QAAI,OAAO,KAAK,OAAO,EAAE,WAAW,EAAG;AACvC,WAAO,KAAK,MAAM,cAAc,OAAO;AAAA,EACzC;AAAA;AAAA,EAGA,UACE,MACA,SACe;AACf,SAAK,QAAQ,OAAO,IAAI;AACxB,UAAM,QACJ,mBAAmB,cACf,IAAI,WAAW,OAAO,IACtB,IAAI;AAAA,MACF,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AACN,WAAO,KAAK,MAAM,UAAU,MAAM,KAAK;AAAA,EACzC;AAAA;AAAA,EAGA,OAAO,MAA6B;AAClC,SAAK,QAAQ,OAAO,IAAI;AACxB,WAAO,KAAK,MAAM,YAAY,IAAI;AAAA,EACpC;AAAA;AAAA,EAGA,QAAuB;AACrB,SAAK,QAAQ,MAAM;AACnB,WAAO,KAAK,MAAM,YAAY;AAAA,EAChC;AAAA,EAEA,UAAgB;AACd,SAAK,MAAc,qBAAY,EAAE;AACjC,SAAK,OAAO,UAAU;AAAA,EACxB;AACF;;;ACjJA,IAAI,kBAAkD;AAEtD,SAAS,cAAuC;AAC9C,MAAI,CAAC,iBAAiB;AACpB,sBAAkB,OAAO,iCAAiC,EAAE,MAAM,CAAC,QAAQ;AACzE,wBAAkB;AAClB,YAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAYO,IAAM,iBAAN,MAAM,gBAAe;AAAA,EAClB;AAAA,EAEA,YAAY,SAAuB,CAAC,GAAG;AAC7C,SAAK,SAAS;AAGd,gBAAY,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAC9B;AAAA,EAEA,OAAO,OAAO,SAAuB,CAAC,GAAmB;AACvD,WAAO,IAAI,gBAAe,MAAM;AAAA,EAClC;AAAA;AAAA,EAGA,MAAM,OAAO,QAAiC;AAC5C,UAAM,WAAW,MAAM,YAAY;AACnC,WAAO,SAAS,OAAO,QAAQ,KAAK,MAAM;AAAA,EAC5C;AAAA;AAAA,EAGA,MAAM,YACJ,QACA,OACA,KAC4B;AAC5B,UAAM,WAAW,MAAM,YAAY;AACnC,UAAM,SAAS,SAAS,aAAa,QAAQ,OAAO,KAAK,KAAK,MAAM;AACpE,WAAO,EAAE,OAAO,OAAO,OAAO,KAAK,OAAO,KAAK,MAAM,OAAO,KAAK;AAAA,EACnE;AACF;;;AC7DO,IAAM,mBAAN,MAAuB;AAAA,EAK5B,YAA6B,UAAmC,CAAC,GAAG;AAAvC;AAAA,EAAwC;AAAA,EAJ7D,gBAAsD;AAAA,EACtD,eAAqD;AAAA,EACrD,eAAe;AAAA,EAIvB,SAAS,UAA4B;AACnC,QAAI,KAAK,eAAe;AACtB,mBAAa,KAAK,aAAa;AAC/B,WAAK,gBAAgB;AAAA,IACvB;AAEA,UAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,QAAQ,cAAc,CAAC;AACtD,SAAK,gBAAgB,WAAW,MAAM;AACpC,WAAK,gBAAgB;AACrB,WAAK,KAAK,QAAQ;AAAA,IACpB,GAAG,KAAK;AAER,UAAM,UAAU,KAAK,QAAQ;AAC7B,QAAI,WAAW,QAAQ,UAAU,KAAK,CAAC,KAAK,cAAc;AACxD,YAAM,OAAO,KAAK;AAAA,QAChB;AAAA,QACA,WAAW,YAAY,IAAI,IAAI,KAAK;AAAA,MACtC;AACA,WAAK,eAAe,WAAW,MAAM;AACnC,aAAK,eAAe;AACpB,YAAI,KAAK,eAAe;AACtB,uBAAa,KAAK,aAAa;AAC/B,eAAK,gBAAgB;AACrB,eAAK,KAAK,QAAQ;AAAA,QACpB;AAAA,MACF,GAAG,IAAI;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,SAAe;AACb,QAAI,KAAK,eAAe;AACtB,mBAAa,KAAK,aAAa;AAC/B,WAAK,gBAAgB;AAAA,IACvB;AACA,QAAI,KAAK,cAAc;AACrB,mBAAa,KAAK,YAAY;AAC9B,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,KAAK,UAA4B;AACvC,SAAK,eAAe,YAAY,IAAI;AACpC,aAAS;AAAA,EACX;AACF;;;AChBA,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAgBrB,SAAS,qBACP,KACA,OACe;AACf,QAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,SAAO;AAAA,IACL,aAAa,MAAM,IAAI,CAAC,UAAU;AAAA,MAChC,SAAS;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,OAAO,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,EAAE;AAAA,MAC1D;AAAA,IACF,EAAE;AAAA,EACJ;AACF;AAEO,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,oBAAI,IAAkB;AAAA,EACtC,mBAAmB,oBAAI,IAAqB;AAAA,EAC5C;AAAA,EACT,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EAEZ,eACN,UACA,QACM;AACN,QAAI;AACF,eAAS,MAAM;AAAA,IACjB,SAAS,KAAK;AACZ,cAAQ,MAAM,mCAAmC,GAAG;AAAA,IACtD;AAAA,EACF;AAAA,EAEA,YAAY,SAA8B;AACxC,SAAK,WAAW,QAAQ;AACxB,SAAK,WAAW,QAAQ;AACxB,SAAK,kBAAkB;AAAA,MACrB,QAAQ,mBAAmB;AAAA,IAC7B;AACA,SAAK,SAAS,cAAc,QAAQ,SAAS,aAAa;AAC1D,SAAK,YAAY,IAAI,iBAAiB;AAAA,MACpC,YAAY,QAAQ,aAAa;AAAA,MACjC,WAAW,QAAQ,aAAa;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,kBAAwB;AAC9B,QAAI,KAAK,UAAW;AACpB,SAAK,UAAU,SAAS,MAAM;AAC5B,WAAK,QAAQ,EAAE,MAAM,CAAC,QAAQ,QAAQ,MAAM,WAAW,GAAG,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,IAAI,QAAc;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,MAAM,MAAY;AACpB,UAAM,OAAO,cAAc,IAAI;AAC/B,QAAI,SAAS,KAAK,OAAQ;AAC1B,SAAK,SAAS;AACd,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA,EAGA,IAAI,cAAuB;AACzB,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,aAAwC;AAC1C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,QAAgB;AAClB,WAAO,CAAC,GAAG,KAAK,cAAc,KAAK,CAAC;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,MAAgC;AACtC,WAAO,KAAK,cAAc,IAAI,cAAc,IAAI,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAQ,MAAY,SAAgC;AACxD,UAAM,IAAI,cAAc,IAAI;AAC5B,QAAI,KAAK,cAAc,IAAI,CAAC,MAAM,QAAS;AAC3C,SAAK,cAAc,IAAI,GAAG,OAAO;AACjC,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,SAAS,QAAQ,GAAG,OAAO;AAAA,MAChC,KAAK,UAAU;AAAA,QACb,kBAAkB,GAAG,KAAK,eAAe;AAAA,QACzC;AAAA,MACF,KAAK,QAAQ,QAAQ;AAAA,IACvB,CAAC;AACD,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ,MAAY,OAA+B;AACvD,UAAM,KAAK,SAAS,QAAQ,cAAc,IAAI,GAAG,KAAK;AACtD,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,UACJ,MACA,SACe;AACf,UAAM,KAAK,SAAS,UAAU,cAAc,IAAI,GAAG,OAAO;AAC1D,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAQ,OAAyD;AACrE,UAAM,aAAgD,CAAC;AACvD,UAAM,eAAuC,CAAC;AAC9C,eAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,KAAK,GAAG;AACnD,YAAM,IAAI,cAAc,IAAI;AAC5B,UAAI,OAAO,YAAY,UAAU;AAC/B,mBAAW,CAAC,IAAI;AAChB;AAAA,MACF;AACA,UAAI,KAAK,cAAc,IAAI,CAAC,MAAM,QAAS;AAC3C,WAAK,cAAc,IAAI,GAAG,OAAO;AACjC,iBAAW,CAAC,IAAI;AAChB,mBAAa,kBAAkB,GAAG,KAAK,eAAe,CAAC,IAAI;AAAA,IAC7D;AACA,QAAI,OAAO,KAAK,UAAU,EAAE,WAAW,EAAG;AAC1C,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,SAAS,QAAQ,UAAU;AAAA,MAChC,KAAK,UAAU,cAAc,YAAY,KAAK,QAAQ,QAAQ;AAAA,IAChE,CAAC;AACD,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,MAA2B;AACtC,UAAM,IAAI,cAAc,IAAI;AAC5B,UAAM,UAAU,KAAK,cAAc,OAAO,CAAC;AAC3C,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,SAAS,OAAO,CAAC;AAAA,MACtB,UACI,KAAK,UAAU,SAAS,kBAAkB,GAAG,KAAK,eAAe,CAAC,IAClE;AAAA,IACN,CAAC;AACD,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,QAAuB;AAC3B,UAAM,OAAO,MAAM;AAAA,MAAK,KAAK,cAAc,KAAK;AAAA,MAAG,CAAC,MAClD,kBAAkB,GAAG,KAAK,eAAe;AAAA,IAC3C;AACA,SAAK,cAAc,MAAM;AACzB,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,SAAS,MAAM;AAAA,MACpB,KAAK,SAAS,IAAI,KAAK,UAAU,aAAa,IAAI,IAAI;AAAA,IACxD,CAAC;AACD,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,UAAuC;AAC/C,SAAK,iBAAiB,IAAI,QAAQ;AAClC,QAAI,KAAK,gBAAgB,QAAW;AAClC,WAAK,eAAe,UAAU,KAAK,WAAW;AAAA,IAChD;AACA,WAAO,MAAM;AACX,WAAK,iBAAiB,OAAO,QAAQ;AAAA,IACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,UAAkC;AACtC,SAAK,UAAU,OAAO;AACtB,UAAM,UAAU,EAAE,KAAK;AACvB,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,KAAK,SAAS,QAAQ,KAAK,MAAM;AAAA,IAClD,SAAS,KAAK;AAIZ,YAAM,QACJ,KAAK,cAAc,OAAO,IACtB,CAAC,GAAG,KAAK,cAAc,KAAK,CAAC,IAC7B,CAAC,KAAK,MAAM;AAClB,eAAS,qBAAqB,KAAK,KAAK;AAAA,IAC1C;AACA,QAAI,YAAY,KAAK,gBAAgB;AACnC,WAAK,cAAc;AACnB,iBAAW,YAAY,KAAK,kBAAkB;AAC5C,aAAK,eAAe,UAAU,MAAM;AAAA,MACtC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAkC;AAChC,WAAO,KAAK,SAAS,WAAW,KAAK,MAAM;AAAA,EAC7C;AAAA,EAEQ,gBAAgB,WAAkC;AACxD,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,MAAM,iBAAiB,SAAS,uBAAuB;AAAA,IACnE;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WACE,MACA,QACA,UACgC;AAChC,UAAM,WAAW,KAAK,gBAAgB,YAAY;AAClD,UAAM,IAAI,cAAc,IAAI;AAC5B,SAAK,cAAc,IAAI,GAAG,MAAM;AAChC,WAAO,SAAS;AAAA,MACd,kBAAkB,GAAG,KAAK,eAAe;AAAA,MACzC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MACE,MACA,QACA,UAC0B;AAC1B,UAAM,WAAW,KAAK,gBAAgB,OAAO;AAC7C,UAAM,IAAI,cAAc,IAAI;AAC5B,SAAK,cAAc,IAAI,GAAG,MAAM;AAChC,WAAO,SAAS;AAAA,MACd,kBAAkB,GAAG,KAAK,eAAe;AAAA,MACzC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,UAAgB;AACd,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AACjB,SAAK,UAAU,OAAO;AACtB,SAAK,iBAAiB,MAAM;AAC5B,SAAK,cAAc,MAAM;AACzB,SAAK,cAAc;AACnB,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;;;ACjYA,IAAM,4BAA4B,iEAAiE,WAA6B;AAEhI,IAAI,wBAA4D;AAEhE,SAAS,oBAAiD;AACxD,MAAI,CAAC,uBAAuB;AAC1B,4BAAwB,OAAO,kCAAkC,EAAE;AAAA,MACjE,CAAC,QAAQ;AACP,gCAAwB;AACxB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AA0BO,IAAM,gBAAN,MAAM,eAAc;AAAA,EACjB;AAAA,EACA,WAA6C;AAAA,EAE7C,YAAY,UAAgC,CAAC,GAAG;AACtD,SAAK,UAAU,QAAQ,WAAW;AAElC,sBAAkB,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACpC;AAAA,EAEA,OAAO,OAAO,UAAgC,CAAC,GAAkB;AAC/D,WAAO,IAAI,eAAc,OAAO;AAAA,EAClC;AAAA,EAEQ,cAAyC;AAC/C,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,KAAK,MAAM,EAAE,MAAM,CAAC,QAAQ;AAC1C,aAAK,WAAW;AAChB,cAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAmC;AACvC,UAAM,MAAM,MAAM,kBAAkB;AACpC,UAAM,IAAI,QAAQ,EAAE,gBAAgB,KAAK,QAAQ,CAAC;AAClD,WAAO,IAAI,IAAI,qBAAqB,EAAE,MAAM;AAAA,EAC9C;AAAA;AAAA,EAGA,MAAM,UAAyB;AAC7B,UAAM,WAAW,KAAK;AACtB,SAAK,WAAW;AAChB,QAAI,UAAU;AACZ,OAAC,MAAM,UAAU,KAAK;AAAA,IACxB;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,UAAU,QAAqC;AACnD,UAAM,WAAW,MAAM,KAAK,YAAY;AACxC,UAAM,UAAU,SAAS,eAAe;AACxC,QAAI;AACF,eAAS,gBAAgB,SAAS,SAAS,MAAM;AACjD,aAAO,SAAS,SAAS,OAAO;AAAA,IAClC,UAAE;AACA,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,eAAe,QAAgD;AACnE,WAAO,oBAAoB,MAAM,KAAK,UAAU,MAAM,CAAC;AAAA,EACzD;AACF;AAKA,SAAS,oBAAoB,KAAgC;AAC3D,QAAM,MAAM,IAAI,UAAU,EAAE,gBAAgB,KAAK,WAAW;AAC5D,QAAM,OAAO,IAAI,cAAc,KAAK;AACpC,MAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,QAAM,WAAW,MAAM,KAAK,KAAK,QAAQ;AACzC,QAAM,aAAa,SAAS;AAAA,IAC1B,CAAC,OACC,GAAG,QAAQ,YAAY,MAAM,OAAO,GAAG,UAAU,SAAS,YAAY;AAAA,EAC1E;AACA,MAAI,WAAW,WAAW,EAAG,QAAO,CAAC;AAErC,QAAM,aAAa,SAChB,OAAO,CAAC,OAAO,CAAC,GAAG,UAAU,SAAS,YAAY,CAAC,EACnD,IAAI,CAAC,OAAO,GAAG,SAAS,EACxB,KAAK,EAAE;AAEV,QAAM,iBAAiB,MAAM,KAAK,KAAK,UAAU,EAC9C,OAAO,CAAC,SAAS,KAAK,SAAS,WAAW,KAAK,KAAK,WAAW,QAAQ,CAAC,EACxE,IAAI,CAAC,SAAS,GAAG,KAAK,IAAI,KAAK,KAAK,KAAK,GAAG,EAC5C,KAAK,GAAG;AAEX,SAAO,WAAW,QAAQ,CAAC,OAAO,UAAU;AAC1C,UAAM,QAAQ,OAAO,MAAM,aAAa,iBAAiB,CAAC,KAAK;AAC/D,UAAM,SAAS,OAAO,MAAM,aAAa,kBAAkB,CAAC,KAAK;AACjE,QAAI,SAAS,KAAK,UAAU,EAAG,QAAO,CAAC;AAEvC,UAAM,QAAQ,MAAM,UAAU,IAAI;AAClC,UAAM,gBAAgB,WAAW;AAEjC,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA,KACE,QAAQ,cAAc,iBAAiB,KAAK,IAAI,MAAM,YAC5C,KAAK,aAAa,MAAM,KAC/B,UAAU,GAAG,MAAM,SAAS;AAAA,MACnC;AAAA,IACF;AAAA,EACF,CAAC;AACH;","names":["Comlink"]}
|