@vedivad/typst-web-service 0.7.12 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -6
- package/dist/analyzer-worker.js +45 -33
- package/dist/analyzer-worker.js.map +1 -1
- package/dist/index.d.ts +125 -111
- package/dist/index.js +239 -233
- package/dist/index.js.map +1 -1
- package/dist/worker.js +28 -15
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/analyzer.ts","../src/rpc.ts","../src/uri.ts","../src/analyzer-session.ts","../src/compiler.ts","../src/formatter.ts","../src/renderer.ts"],"sourcesContent":["import * as Comlink from \"comlink\";\nimport type { LspDiagnostic } from \"./analyzer-types.js\";\nimport { createAnalyzerWorker } from \"./rpc.js\";\nimport { normalizeUntitledUri } from \"./uri.js\";\n\nexport type { LspDiagnostic };\n\nexport type DiagnosticsListener = (\n uri: string,\n diagnostics: LspDiagnostic[],\n) => void;\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\ninterface AnalyzerWorkerAPI {\n init(\n wasmUrl: string,\n onDiagnostics: (uri: string, diagnostics: LspDiagnostic[]) => void,\n ): Promise<void>;\n didOpen(uri: string, content: string): Promise<void>;\n didClose(uri: string): Promise<void>;\n didChange(uri: string, version: number, content: string): Promise<void>;\n completion(uri: string, line: number, character: number): Promise<unknown>;\n hover(uri: string, line: number, character: number): Promise<unknown>;\n destroy(): void;\n}\n\n/**\n * Manages a tinymist language server in a Web Worker. Provides LSP-based\n * diagnostics, completion, and hover for Typst documents.\n *\n * Diagnostics are push-based: call `didChange()` to notify the analyzer of\n * content changes, and receive diagnostics via `onDiagnostics()` listeners\n * whenever tinymist publishes them.\n *\n * const analyzer = await TypstAnalyzer.create({ wasmUrl: '...' });\n * analyzer.onDiagnostics((uri, diags) => { ... });\n */\nexport class TypstAnalyzer {\n private readonly proxy: Comlink.Remote<AnalyzerWorkerAPI>;\n private readonly worker: Worker;\n private versionCounter = 0;\n private openedUris = new Set<string>();\n private diagnosticsListeners = new Set<DiagnosticsListener>();\n\n private constructor(\n worker: Worker,\n proxy: Comlink.Remote<AnalyzerWorkerAPI>,\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<AnalyzerWorkerAPI>(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(\n absoluteWasmUrl,\n Comlink.proxy((uri: string, diagnostics: LspDiagnostic[]) => {\n const normalizedUri = normalizeUntitledUri(uri);\n for (const listener of analyzer.diagnosticsListeners) {\n listener(normalizedUri, diagnostics);\n }\n }),\n );\n\n return analyzer;\n }\n\n /**\n * Register a listener for push-based diagnostics.\n * Returns an unsubscribe function.\n */\n onDiagnostics(listener: DiagnosticsListener): () => void {\n this.diagnosticsListeners.add(listener);\n return () => this.diagnosticsListeners.delete(listener);\n }\n\n async didOpen(uri: string, content: string): Promise<void> {\n await this.proxy.didOpen(uri, content);\n this.openedUris.add(uri);\n }\n\n async didClose(uri: string): Promise<void> {\n if (!this.openedUris.has(uri)) return;\n await this.proxy.didClose(uri);\n this.openedUris.delete(uri);\n }\n\n /**\n * Notify the analyzer that a document has changed.\n * Diagnostics will arrive asynchronously via `onDiagnostics()` listeners.\n */\n async didChange(uri: string, content: string): Promise<void> {\n if (!this.openedUris.has(uri)) {\n await this.didOpen(uri, content);\n return;\n }\n const version = ++this.versionCounter;\n await this.proxy.didChange(uri, version, content);\n }\n\n async completion(\n uri: string,\n line: number,\n character: number,\n ): Promise<unknown> {\n return this.proxy.completion(uri, line, character);\n }\n\n async hover(uri: string, line: number, character: number): Promise<unknown> {\n return this.proxy.hover(uri, line, character);\n }\n\n destroy(): void {\n this.diagnosticsListeners.clear();\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","export function normalizeUntitledUri(uri: string): string {\n if (!uri.startsWith(\"untitled:\")) return uri;\n return `untitled:${uri.slice(\"untitled:\".length).replace(/^\\/+/, \"\")}`;\n}\n\nexport function normalizePath(path: string): string {\n return path.startsWith(\"/\") ? path : `/${path}`;\n}\n\nexport function normalizeRoot(rootPath: string): string {\n const root = normalizePath(rootPath);\n return root === \"/\" ? \"\" : root.replace(/\\/+$/, \"\");\n}\n","import type { LspDiagnostic } from \"./analyzer-types.js\";\nimport type { TypstAnalyzer } from \"./analyzer.js\";\nimport { normalizePath, normalizeRoot } from \"./uri.js\";\n\nexport type DiagnosticsSubscriber = (diagnostics: LspDiagnostic[]) => void;\n\nexport interface AnalyzerSessionOptions {\n analyzer: Pick<\n TypstAnalyzer,\n \"didOpen\" | \"didChange\" | \"completion\" | \"hover\" | \"onDiagnostics\"\n >;\n /** Project root used to build stable in-memory analyzer URIs. Default: \"/project\". */\n rootPath?: string;\n /** Entry file path within the project. Synced last to ensure dependencies load first. Default: \"/main.typ\". */\n entryPath?: string;\n}\n\n/**\n * Synchronizes an in-memory Typst project with a TypstAnalyzer.\n * Handles multi-file ordering, request queueing, and diagnostic subscriptions.\n *\n * Diagnostics arrive via the analyzer's push mechanism and are forwarded\n * to subscribers registered with `subscribe()`.\n *\n * const session = new AnalyzerSession({ analyzer });\n * session.subscribe(\"/main.typ\", (diags) => { ... });\n * await session.sync(\"/main.typ\", files);\n */\nexport class AnalyzerSession {\n private readonly analyzer: AnalyzerSessionOptions[\"analyzer\"];\n private readonly rootPath: string;\n private readonly entryPath: string;\n private readonly syncedFiles = new Map<string, string>();\n private queue: Promise<void> = Promise.resolve();\n\n // Diagnostic subscription state\n private readonly listenersByUri = new Map<\n string,\n Set<DiagnosticsSubscriber>\n >();\n /** Last push received per URI. Replayed on subscribe() so tab-back shows correct diagnostics instantly. */\n private readonly diagnosticsCache = new Map<string, LspDiagnostic[]>();\n private readonly unsubscribeAnalyzer: () => void;\n\n constructor(options: AnalyzerSessionOptions) {\n this.analyzer = options.analyzer;\n this.rootPath = normalizeRoot(options.rootPath ?? \"/project\");\n this.entryPath = normalizePath(options.entryPath ?? \"/main.typ\");\n\n this.unsubscribeAnalyzer = this.analyzer.onDiagnostics(\n (uri, diagnostics) => {\n this.diagnosticsCache.set(uri, diagnostics);\n const listeners = this.listenersByUri.get(uri);\n if (!listeners) return;\n for (const listener of listeners) listener(diagnostics);\n },\n );\n }\n\n /** Build a tinymist URI from a project-relative path. */\n toUri(path: string): string {\n const root = this.rootPath.replace(/^\\//, \"\");\n return `untitled:${root}${normalizePath(path)}`;\n }\n\n /**\n * Subscribe to push-based diagnostics for a file path.\n * Returns an unsubscribe function.\n */\n subscribe(path: string, listener: DiagnosticsSubscriber): () => void {\n const uri = this.toUri(path);\n\n let listeners = this.listenersByUri.get(uri);\n if (!listeners) {\n listeners = new Set();\n this.listenersByUri.set(uri, listeners);\n }\n listeners.add(listener);\n\n // Replay the last known diagnostics immediately so the UI reflects the\n // correct state without waiting for the next tinymist push.\n const cached = this.diagnosticsCache.get(uri);\n if (cached) listener(cached);\n\n return () => {\n const current = this.listenersByUri.get(uri);\n if (!current) return;\n current.delete(listener);\n if (current.size === 0) this.listenersByUri.delete(uri);\n };\n }\n\n /**\n * Sync all project files with the analyzer.\n * `files` must include the active file's current content under `path`.\n *\n * If the active file's content hasn't changed since the last sync, a\n * lightweight hover is triggered to ensure the analyzer re-analyzes with\n * the current project state and publishes fresh diagnostics.\n */\n async sync(path: string, files: Record<string, string>): Promise<void> {\n await this.enqueue(async () => {\n const changed = await this.syncFiles(path, files);\n\n // When the active file's content is unchanged, the analyzer won't\n // publish fresh diagnostics on its own. A hover request forces it\n // to re-evaluate with the (possibly updated) project context.\n if (!changed) {\n try {\n await this.analyzer.hover(this.toUri(normalizePath(path)), 0, 0);\n } catch {\n /* best-effort — the hover result is unused */\n }\n }\n\n // Clean up files that were removed from the project.\n for (const filePath of this.syncedFiles.keys()) {\n if (!Object.hasOwn(files, filePath)) {\n this.syncedFiles.delete(filePath);\n }\n }\n });\n }\n\n /**\n * Sync files and request completions at the given position.\n * Returns the raw LSP CompletionList/CompletionItem[] from tinymist.\n */\n async completion(\n path: string,\n files: Record<string, string>,\n line: number,\n character: number,\n ): Promise<unknown> {\n return this.enqueue(async () => {\n await this.syncFiles(path, files);\n return this.analyzer.completion(\n this.toUri(normalizePath(path)),\n line,\n character,\n );\n });\n }\n\n /**\n * Sync files and request hover info at the given position.\n * Returns the raw LSP Hover result from tinymist.\n */\n async hover(\n path: string,\n files: Record<string, string>,\n line: number,\n character: number,\n ): Promise<unknown> {\n return this.enqueue(async () => {\n await this.syncFiles(path, files);\n return this.analyzer.hover(\n this.toUri(normalizePath(path)),\n line,\n character,\n );\n });\n }\n\n destroy(): void {\n this.unsubscribeAnalyzer();\n this.listenersByUri.clear();\n this.diagnosticsCache.clear();\n }\n\n /**\n * Sync all project files: dependencies first, active file last.\n * Returns whether the active file's content was actually sent to the analyzer.\n */\n private async syncFiles(\n path: string,\n files: Record<string, string>,\n ): Promise<boolean> {\n const activePath = normalizePath(path);\n for (const filePath of this.orderedPaths(files)) {\n if (filePath === activePath) continue;\n await this.syncFile(filePath, files[filePath]);\n }\n return this.syncFile(activePath, files[activePath]);\n }\n\n /** Sync a single file. Returns true if content was sent to the analyzer. */\n private async syncFile(path: string, content: string): Promise<boolean> {\n const prev = this.syncedFiles.get(path);\n if (prev == null) {\n await this.analyzer.didOpen(this.toUri(path), content);\n } else if (prev !== content) {\n await this.analyzer.didChange(this.toUri(path), content);\n } else {\n return false;\n }\n this.syncedFiles.set(path, content);\n return true;\n }\n\n private orderedPaths(files: Record<string, string>): string[] {\n return Object.keys(files)\n .map((p) => normalizePath(p))\n .sort((a, b) => {\n if (a === this.entryPath) return 1;\n if (b === this.entryPath) return -1;\n return a.localeCompare(b);\n });\n }\n\n private enqueue<T>(task: () => Promise<T>): Promise<T> {\n const run = this.queue.then(task, task);\n this.queue = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }\n}\n","import * as Comlink from \"comlink\";\nimport { createWorker } from \"./rpc.js\";\nimport type { DiagnosticMessage } from \"./types.js\";\n\ninterface CompilerWorkerAPI {\n init(wasmUrl: string, fontUrls: string[], packages: boolean): Promise<void>;\n compile(\n files: Record<string, string>,\n ): Promise<{ diagnostics: DiagnosticMessage[]; vector?: Uint8Array }>;\n compilePdf(files: Record<string, string>): Promise<Uint8Array>;\n addSource(path: string, source: string): void;\n mapShadow(path: string, content: Uint8Array): void;\n unmapShadow(path: string): void;\n resetShadow(): void;\n destroy(): void;\n}\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/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 =\n \"https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-web-compiler@0.7.0-rc2/pkg/typst_ts_web_compiler_bg.wasm\";\n\nfunction toFiles(\n source: string | Record<string, string>,\n): Record<string, string> {\n return typeof source === \"string\" ? { \"/main.typ\": source } : source;\n}\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<CompilerWorkerAPI>;\n private readonly worker: Worker;\n private readonly encoder = new TextEncoder();\n\n /** The most recent vector artifact from a compile, if any. */\n lastVector?: Uint8Array;\n\n private constructor(\n worker: Worker,\n proxy: Comlink.Remote<CompilerWorkerAPI>,\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<CompilerWorkerAPI>(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 /** Compile a single source string (treated as /main.typ) or a map of files. */\n async compile(\n source: string | Record<string, string>,\n ): Promise<CompileResult> {\n const result = await this.proxy.compile(toFiles(source));\n if (result.vector) this.lastVector = result.vector;\n return result;\n }\n\n /** Compile to PDF from a single source string (treated as /main.typ) or a map of files. */\n async compilePdf(\n source: string | Record<string, string>,\n ): Promise<Uint8Array> {\n return this.proxy.compilePdf(toFiles(source));\n }\n\n /** Add or overwrite a text source file. */\n async addSource(path: string, source: string): Promise<void> {\n await this.proxy.addSource(path, source);\n }\n\n /** Add or overwrite an in-memory shadow file (text or binary). */\n async mapShadow(path: string, content: Uint8Array): Promise<void> {\n await this.proxy.mapShadow(path, content);\n }\n\n /** Remove an in-memory shadow file by path. */\n async unmapShadow(path: string): Promise<void> {\n await this.proxy.unmapShadow(path);\n }\n\n /**\n * Clear all shadow files held by the compiler.\n * Note: this also clears files previously added via addSource in the compiler runtime.\n */\n async resetShadow(): Promise<void> {\n await this.proxy.resetShadow();\n }\n\n /** Add or overwrite a text file in the virtual compiler filesystem. */\n async setText(path: string, source: string): Promise<void> {\n await this.mapShadow(path, this.encoder.encode(source));\n }\n\n /** Add or overwrite a JSON file in the virtual compiler filesystem. */\n async setJson(\n path: string,\n value: unknown,\n replacer?: (this: unknown, key: string, value: unknown) => unknown,\n space?: string | number,\n ): Promise<void> {\n await this.setText(path, JSON.stringify(value, replacer, space));\n }\n\n /** Add or overwrite a binary file in the virtual compiler filesystem. */\n async setBinary(\n path: string,\n content: ArrayBuffer | ArrayBufferView,\n ): Promise<void> {\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 await this.mapShadow(path, bytes);\n }\n\n /** Remove a file from the virtual compiler filesystem. */\n async remove(path: string): Promise<void> {\n await this.unmapShadow(path);\n }\n\n /** Clear all virtual files from the compiler filesystem. */\n async clear(): Promise<void> {\n await this.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","/** 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\nconst DEFAULT_RENDERER_WASM_URL =\n \"https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-renderer@0.7.0-rc2/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\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(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"],"mappings":"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","names":["proxy","Comlink","proxy"]}
|
|
1
|
+
{"version":3,"sources":["../src/analyzer.ts","../src/rpc.ts","../src/uri.ts","../src/compiler.ts","../src/formatter.ts","../src/project.ts","../src/renderer.ts"],"sourcesContent":["import * as Comlink from \"comlink\";\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\ninterface AnalyzerWorkerAPI {\n init(wasmUrl: string): Promise<void>;\n didOpen(uri: string, content: string): Promise<void>;\n didClose(uri: string): Promise<void>;\n didChange(uri: string, version: number, content: string): Promise<void>;\n didChangeMany(\n opens: Array<{ uri: string; content: string }>,\n changes: Array<{ uri: string; version: number; content: string }>,\n ): Promise<void>;\n didCloseMany(uris: string[]): Promise<void>;\n completion(uri: string, line: number, character: number): Promise<unknown>;\n hover(uri: string, line: number, character: number): Promise<unknown>;\n destroy(): void;\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<AnalyzerWorkerAPI>;\n private readonly worker: Worker;\n private versionCounter = 0;\n private openedUris = new Set<string>();\n\n private constructor(\n worker: Worker,\n proxy: Comlink.Remote<AnalyzerWorkerAPI>,\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<AnalyzerWorkerAPI>(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.openedUris.add(uri);\n await this.proxy.didOpen(uri, content);\n }\n\n async didClose(uri: string): Promise<void> {\n if (!this.openedUris.delete(uri)) return;\n await this.proxy.didClose(uri);\n }\n\n /**\n * Notify the analyzer that a document has changed.\n */\n async didChange(uri: string, content: string): Promise<void> {\n if (!this.openedUris.has(uri)) {\n await this.didOpen(uri, content);\n return;\n }\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 */\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.openedUris.has(uri)) {\n changes.push({ uri, version: ++this.versionCounter, content });\n } else {\n opens.push({ uri, content });\n this.openedUris.add(uri);\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.openedUris.delete(uri)) toClose.push(uri);\n }\n if (toClose.length === 0) return;\n await this.proxy.didCloseMany(toClose);\n }\n\n async completion(\n uri: string,\n line: number,\n character: number,\n ): Promise<unknown> {\n return this.proxy.completion(uri, line, character);\n }\n\n async hover(uri: string, line: number, character: number): Promise<unknown> {\n return this.proxy.hover(uri, line, character);\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","export function normalizeUntitledUri(uri: string): string {\n if (!uri.startsWith(\"untitled:\")) return uri;\n return `untitled:${uri.slice(\"untitled:\".length).replace(/^\\/+/, \"\")}`;\n}\n\nexport function normalizePath(path: string): string {\n return path.startsWith(\"/\") ? path : `/${path}`;\n}\n\nexport function normalizeRoot(rootPath: string): string {\n const root = normalizePath(rootPath);\n return root === \"/\" ? \"\" : root.replace(/\\/+$/, \"\");\n}\n","import * as Comlink from \"comlink\";\nimport { createWorker } from \"./rpc.js\";\nimport type { DiagnosticMessage } from \"./types.js\";\n\ninterface CompilerWorkerAPI {\n init(wasmUrl: string, fontUrls: string[], packages: boolean): Promise<void>;\n compile(\n files?: Record<string, string>,\n entry?: string,\n ): Promise<{ diagnostics: DiagnosticMessage[]; vector?: Uint8Array }>;\n compilePdf(\n files?: Record<string, string>,\n entry?: string,\n ): Promise<Uint8Array>;\n mapShadow(path: string, content: Uint8Array): void;\n mapShadowMany(files: Record<string, Uint8Array>): void;\n unmapShadow(path: string): void;\n resetShadow(): void;\n destroy(): void;\n}\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/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 =\n \"https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-web-compiler@0.7.0-rc2/pkg/typst_ts_web_compiler_bg.wasm\";\n\nconst DEFAULT_ENTRY = \"/main.typ\";\n\nfunction toFiles(\n source?: string | Record<string, string>,\n entry?: string,\n): Record<string, string> | undefined {\n if (source === undefined) return undefined;\n return typeof source === \"string\"\n ? { [entry ?? DEFAULT_ENTRY]: source }\n : source;\n}\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<CompilerWorkerAPI>;\n private readonly worker: Worker;\n private readonly encoder = new TextEncoder();\n\n /** The most recent vector artifact from a compile, if any. */\n lastVector?: Uint8Array;\n\n private constructor(\n worker: Worker,\n proxy: Comlink.Remote<CompilerWorkerAPI>,\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<CompilerWorkerAPI>(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. Pass a source string (written to the entry path) or a map of\n * files to register before compiling; omit to compile whatever is currently\n * in the VFS (populated via setText/setBinary/setJson/setMany).\n * Defaults to compiling \"/main.typ\"; override with `entry`.\n */\n async compile(\n source?: string | Record<string, string>,\n entry?: string,\n ): Promise<CompileResult> {\n const result = await this.proxy.compile(toFiles(source, entry), entry);\n if (result.vector) this.lastVector = result.vector;\n return result;\n }\n\n /**\n * Compile to PDF. Pass a source string (written to the entry path) or a map\n * of files to register before compiling; omit to compile whatever is\n * currently in the VFS (populated via setText/setBinary/setJson/setMany).\n * Defaults to compiling \"/main.typ\"; override with `entry`.\n */\n compilePdf(\n source?: string | Record<string, string>,\n entry?: string,\n ): Promise<Uint8Array> {\n return this.proxy.compilePdf(toFiles(source, entry), entry);\n }\n\n /** Add or overwrite a text file in the virtual compiler filesystem. */\n setText(path: string, source: string): Promise<void> {\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 passed\n * through.\n */\n setMany(files: Record<string, string | Uint8Array>): Promise<void> {\n const encoded: Record<string, Uint8Array> = {};\n for (const [path, content] of Object.entries(files)) {\n encoded[path] =\n typeof content === \"string\" ? this.encoder.encode(content) : content;\n }\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 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 return this.proxy.unmapShadow(path);\n }\n\n /** Clear all virtual files from the compiler filesystem. */\n clear(): Promise<void> {\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","import type { TypstAnalyzer } from \"./analyzer.js\";\nimport type { CompileResult, TypstCompiler } from \"./compiler.js\";\nimport { normalizePath, normalizeRoot } from \"./uri.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 * Project root used to build stable analyzer URIs. Default: \"/project\".\n * URIs are formed as `untitled:<root-without-leading-slash><path>` — so\n * `/main.typ` becomes `untitled:project/main.typ`.\n */\n rootPath?: string;\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 class TypstProject {\n private readonly compiler: TypstCompiler;\n private readonly analyzer?: TypstAnalyzer;\n private readonly rootPath: string;\n private readonly trackedTextPaths = new Set<string>();\n /** Last content written via setText/setMany, per path. Used to skip redundant writes to compiler + analyzer. */\n private readonly lastSyncedContent = new Map<string, string>();\n private _entry: string;\n\n constructor(options: TypstProjectOptions) {\n this.compiler = options.compiler;\n this.analyzer = options.analyzer;\n this.rootPath = normalizeRoot(options.rootPath ?? DEFAULT_ROOT);\n this._entry = normalizePath(options.entry ?? DEFAULT_ENTRY);\n }\n\n /** Current entry file path. */\n get entry(): string {\n return this._entry;\n }\n\n /** Whether an analyzer is attached. */\n get hasAnalyzer(): boolean {\n return this.analyzer !== undefined;\n }\n\n /** Change the sticky entry file used by subsequent compile() calls. */\n setEntry(path: string): void {\n this._entry = 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. Redundant\n * calls with unchanged content are skipped.\n */\n async setText(path: string, content: string): Promise<void> {\n const p = normalizePath(path);\n this.trackedTextPaths.add(p);\n if (this.lastSyncedContent.get(p) === content) return;\n this.lastSyncedContent.set(p, content);\n const ops: Array<Promise<void>> = [this.compiler.setText(p, content)];\n if (this.analyzer) {\n ops.push(this.analyzer.didChange(this.toUri(p), content));\n }\n await Promise.all(ops);\n }\n\n /**\n * Add or overwrite a JSON file. Compiler-only — the analyzer does not track\n * data files.\n */\n setJson(path: string, value: unknown): Promise<void> {\n return this.compiler.setJson(normalizePath(path), value);\n }\n\n /** Add or overwrite a binary file. Compiler-only. */\n setBinary(\n path: string,\n content: ArrayBuffer | ArrayBufferView,\n ): Promise<void> {\n return this.compiler.setBinary(normalizePath(path), content);\n }\n\n /**\n * Batch set multiple files. Strings route to both compiler and analyzer;\n * Uint8Array entries go to the compiler only.\n */\n async setMany(files: Record<string, string | Uint8Array>): Promise<void> {\n const normalized: Record<string, string | Uint8Array> = {};\n for (const [path, content] of Object.entries(files)) {\n normalized[normalizePath(path)] = content;\n }\n const compilerOp = this.compiler.setMany(normalized);\n const analyzerOp = (async () => {\n if (!this.analyzer) return;\n const docs: Record<string, string> = {};\n for (const [path, content] of Object.entries(normalized)) {\n if (typeof content !== \"string\") continue;\n this.trackedTextPaths.add(path);\n if (this.lastSyncedContent.get(path) === content) continue;\n this.lastSyncedContent.set(path, content);\n docs[this.toUri(path)] = content;\n }\n if (Object.keys(docs).length > 0) {\n await this.analyzer.didChangeMany(docs);\n }\n })();\n await Promise.all([compilerOp, analyzerOp]);\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: string): Promise<void> {\n const p = normalizePath(path);\n const wasText = this.trackedTextPaths.delete(p);\n this.lastSyncedContent.delete(p);\n const ops: Array<Promise<void>> = [this.compiler.remove(p)];\n if (this.analyzer && wasText) {\n ops.push(this.analyzer.didClose(this.toUri(p)));\n }\n await Promise.all(ops);\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.trackedTextPaths, (p) => this.toUri(p));\n this.trackedTextPaths.clear();\n this.lastSyncedContent.clear();\n const compilerOp = this.compiler.clear();\n const analyzerOp =\n this.analyzer && uris.length > 0\n ? this.analyzer.didCloseMany(uris)\n : Promise.resolve();\n await Promise.all([compilerOp, analyzerOp]);\n }\n\n /** Compile the current VFS state using the sticky entry. */\n compile(): Promise<CompileResult> {\n return this.compiler.compile(undefined, this._entry);\n }\n\n /** Compile the current VFS state to PDF using the sticky entry. */\n compilePdf(): Promise<Uint8Array> {\n return this.compiler.compilePdf(undefined, 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 /** Request completions at the given position. Throws when no analyzer is attached. */\n completion(path: string, line: number, character: number): Promise<unknown> {\n return this.requireAnalyzer(\"completion\").completion(\n this.toUri(normalizePath(path)),\n line,\n character,\n );\n }\n\n /** Request hover info at the given position. Throws when no analyzer is attached. */\n hover(path: string, line: number, character: number): Promise<unknown> {\n return this.requireAnalyzer(\"hover\").hover(\n this.toUri(normalizePath(path)),\n line,\n character,\n );\n }\n\n private toUri(path: string): string {\n const root = this.rootPath.replace(/^\\//, \"\");\n return `untitled:${root}${normalizePath(path)}`;\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\nconst DEFAULT_RENDERER_WASM_URL =\n \"https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-renderer@0.7.0-rc2/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\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"],"mappings":"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","names":["Comlink","DEFAULT_ENTRY"]}
|
package/dist/worker.js
CHANGED
|
@@ -2102,6 +2102,13 @@ var FetchPackageRegistry = class {
|
|
|
2102
2102
|
}
|
|
2103
2103
|
};
|
|
2104
2104
|
|
|
2105
|
+
// src/diagnostics-sort.ts
|
|
2106
|
+
function sortDiagnosticsByFileAndRange(diagnostics) {
|
|
2107
|
+
return [...diagnostics].sort(
|
|
2108
|
+
(a, b) => a.path.localeCompare(b.path) || a.range.startLine - b.range.startLine || a.range.startCol - b.range.startCol || a.range.endLine - b.range.endLine || a.range.endCol - b.range.endCol || a.message.localeCompare(b.message)
|
|
2109
|
+
);
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2105
2112
|
// src/worker.ts
|
|
2106
2113
|
var MAIN_FILE = "/main.typ";
|
|
2107
2114
|
var CompilerWorker = class {
|
|
@@ -2124,17 +2131,19 @@ var CompilerWorker = class {
|
|
|
2124
2131
|
]
|
|
2125
2132
|
});
|
|
2126
2133
|
}
|
|
2127
|
-
async compile(files) {
|
|
2134
|
+
async compile(files, entry) {
|
|
2128
2135
|
if (!this.compiler) throw new Error("Compiler not initialized");
|
|
2129
|
-
|
|
2130
|
-
|
|
2136
|
+
if (files) {
|
|
2137
|
+
for (const [path, source] of Object.entries(files)) {
|
|
2138
|
+
this.compiler.addSource(path, source);
|
|
2139
|
+
}
|
|
2131
2140
|
}
|
|
2132
2141
|
const result = await this.compiler.compile({
|
|
2133
|
-
mainFilePath: MAIN_FILE,
|
|
2142
|
+
mainFilePath: entry ?? MAIN_FILE,
|
|
2134
2143
|
diagnostics: "full"
|
|
2135
2144
|
});
|
|
2136
|
-
const diagnostics = (
|
|
2137
|
-
(d) => {
|
|
2145
|
+
const diagnostics = sortDiagnosticsByFileAndRange(
|
|
2146
|
+
(result.diagnostics ?? []).flatMap((d) => {
|
|
2138
2147
|
const m = d.range.match(/(\d+):(\d+)-(\d+):(\d+)/);
|
|
2139
2148
|
if (!m) {
|
|
2140
2149
|
console.warn(
|
|
@@ -2154,7 +2163,7 @@ var CompilerWorker = class {
|
|
|
2154
2163
|
}
|
|
2155
2164
|
}
|
|
2156
2165
|
];
|
|
2157
|
-
}
|
|
2166
|
+
})
|
|
2158
2167
|
);
|
|
2159
2168
|
const vector = result.result ?? void 0;
|
|
2160
2169
|
if (vector) {
|
|
@@ -2164,13 +2173,15 @@ var CompilerWorker = class {
|
|
|
2164
2173
|
}
|
|
2165
2174
|
return { diagnostics };
|
|
2166
2175
|
}
|
|
2167
|
-
async compilePdf(files) {
|
|
2176
|
+
async compilePdf(files, entry) {
|
|
2168
2177
|
if (!this.compiler) throw new Error("Compiler not initialized");
|
|
2169
|
-
|
|
2170
|
-
|
|
2178
|
+
if (files) {
|
|
2179
|
+
for (const [path, source] of Object.entries(files)) {
|
|
2180
|
+
this.compiler.addSource(path, source);
|
|
2181
|
+
}
|
|
2171
2182
|
}
|
|
2172
2183
|
const result = await this.compiler.compile({
|
|
2173
|
-
mainFilePath: MAIN_FILE,
|
|
2184
|
+
mainFilePath: entry ?? MAIN_FILE,
|
|
2174
2185
|
format: CompileFormatEnum.pdf,
|
|
2175
2186
|
diagnostics: "none"
|
|
2176
2187
|
});
|
|
@@ -2179,14 +2190,16 @@ var CompilerWorker = class {
|
|
|
2179
2190
|
result.result.buffer
|
|
2180
2191
|
]);
|
|
2181
2192
|
}
|
|
2182
|
-
addSource(path, source) {
|
|
2183
|
-
if (!this.compiler) throw new Error("Compiler not initialized");
|
|
2184
|
-
this.compiler.addSource(path, source);
|
|
2185
|
-
}
|
|
2186
2193
|
mapShadow(path, content) {
|
|
2187
2194
|
if (!this.compiler) throw new Error("Compiler not initialized");
|
|
2188
2195
|
this.compiler.mapShadow(path, content);
|
|
2189
2196
|
}
|
|
2197
|
+
mapShadowMany(files) {
|
|
2198
|
+
if (!this.compiler) throw new Error("Compiler not initialized");
|
|
2199
|
+
for (const [path, content] of Object.entries(files)) {
|
|
2200
|
+
this.compiler.mapShadow(path, content);
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2190
2203
|
unmapShadow(path) {
|
|
2191
2204
|
if (!this.compiler) throw new Error("Compiler not initialized");
|
|
2192
2205
|
this.compiler.unmapShadow(path);
|