/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // main.ts var main_exports = {}; __export(main_exports, { default: () => TypstMathPlugin }); module.exports = __toCommonJS(main_exports); var import_child_process = require("child_process"); var import_fs = require("fs"); var import_obsidian = require("obsidian"); var os = __toESM(require("os")); var path = __toESM(require("path")); var DEFAULT_SETTINGS = { typstPath: "typst", enableInlineMath: true, enableDisplayMath: true, debugMode: false, showDetailedErrors: false, useWatchMode: false, enableLivePreview: true, forceSyncCompile: false, syncOnlyDuringExport: true }; var TypstMathPlugin = class extends import_obsidian.Plugin { constructor() { super(...arguments); // Internal flag set when a print/export flow is active this.exportInProgress = false; // Hold original window.print so we can restore it on unload this._originalWindowPrint = null; // Keep reference to matchMedia listener so we can remove it this._printMediaListener = null; this.watchers = /* @__PURE__ */ new Map(); // Store typst source content for blocks that are pending compilation this.pendingTypstContent = /* @__PURE__ */ new Map(); this.renderCache = /* @__PURE__ */ new Map(); this.handleBeforePrint = () => { this.exportInProgress = true; if (this.settings.debugMode) console.log("Typst plugin: export/print started"); }; this.handleAfterPrint = () => { this.exportInProgress = false; if (this.settings.debugMode) console.log("Typst plugin: export/print finished"); }; } async onload() { var _a; await this.loadSettings(); this.tempDir = path.join(os.tmpdir(), "obsidian-typst-math"); await this.ensureTempDir(); this.registerMarkdownCodeBlockProcessor( "math", this.processMathBlock.bind(this) ); this.registerMarkdownCodeBlockProcessor( "typst", this.processMathBlock.bind(this) ); await (0, import_obsidian.loadMathJax)(); if (!globalThis.MathJax) { new import_obsidian.Notice("MathJax failed to load. Math rendering may not work."); console.error("MathJax failed to load."); } else { this.originalTex2chtml = globalThis.MathJax.tex2chtml; globalThis.MathJax.tex2chtml = (latex, options) => { return this.renderWithTypst(latex, options); }; const activeView = this.app.workspace.getActiveViewOfType(import_obsidian.MarkdownView); if (activeView) { (_a = activeView.previewMode) == null ? void 0 : _a.rerender(true); if (this.settings.enableLivePreview) { const editor = activeView.editor; if (editor) { const cursor = editor.getCursor(); editor.setCursor(cursor); } } } } if (typeof window !== "undefined") { window.addEventListener("beforeprint", this.handleBeforePrint); window.addEventListener("afterprint", this.handleAfterPrint); try { if (typeof window.print === "function") { this._originalWindowPrint = window.print.bind(window); window.print = (...args) => { this.handleBeforePrint(); try { const res = this._originalWindowPrint(...args); setTimeout(() => this.handleAfterPrint(), 1500); return res; } catch (e) { this.handleAfterPrint(); throw e; } }; } } catch (e) { if (this.settings.debugMode) console.warn("Failed to patch window.print", e); } try { const mql = window.matchMedia && window.matchMedia("print"); if (mql) { this._printMediaListener = (ev) => { if (ev.matches) this.handleBeforePrint(); else this.handleAfterPrint(); }; if (typeof mql.addEventListener === "function") { mql.addEventListener("change", this._printMediaListener); } else if (typeof mql.addListener === "function") { mql.addListener(this._printMediaListener); } } } catch (e) { if (this.settings.debugMode) console.warn("Failed to attach matchMedia print listener", e); } } this.addSettingTab(new TypstMathSettingTab(this.app, this)); this.addCommand({ id: "typst-prepare-export", name: "Typst: Prepare export (sync compile all math)", callback: () => { void this.prepareExport(); } }); console.log("Typst Math Plugin loaded"); } async onunload() { var _a; if (this.originalTex2chtml && globalThis.MathJax) { globalThis.MathJax.tex2chtml = this.originalTex2chtml; (_a = this.app.workspace.getActiveViewOfType(import_obsidian.MarkdownView)) == null ? void 0 : _a.previewMode.rerender(true); } for (const [id, process] of this.watchers) { process.kill(); } this.watchers.clear(); try { await import_fs.promises.rm(this.tempDir, { recursive: true, force: true }); } catch (error) { console.error("Error cleaning up temp directory:", error); } try { if (typeof window !== "undefined") { window.removeEventListener("beforeprint", this.handleBeforePrint); window.removeEventListener("afterprint", this.handleAfterPrint); if (this._printMediaListener && window.matchMedia) { const mql = window.matchMedia("print"); if (mql) { if (typeof mql.removeEventListener === "function") { mql.removeEventListener("change", this._printMediaListener); } else if (typeof mql.removeListener === "function") { mql.removeListener(this._printMediaListener); } } } if (this._originalWindowPrint) { try { window.print = this._originalWindowPrint; } catch (e) { } } } } catch (e) { if (this.settings.debugMode) console.warn("Error restoring print handlers", e); } console.log("Typst Math Plugin unloaded"); } async loadSettings() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); } async saveSettings() { await this.saveData(this.settings); } async ensureTempDir() { try { await import_fs.promises.mkdir(this.tempDir, { recursive: true }); } catch (error) { console.error("Error creating temp directory:", error); } } formatError(error, isInline = false) { const errorMsg = typeof error === "string" ? error : error.message; let friendlyMsg = "There was an error with your Typst code"; if (errorMsg.includes("ENOENT") || errorMsg.includes("not found")) { friendlyMsg = "Typst CLI not found"; } else if (errorMsg.includes("syntax error") || errorMsg.includes("unexpected")) { friendlyMsg = "Syntax error in Typst code"; } else if (errorMsg.includes("undefined")) { friendlyMsg = "Undefined symbol or function"; } else if (errorMsg.includes("type")) { friendlyMsg = "Type error in expression"; } const errorClass = isInline ? "typst-error-inline" : "typst-error"; if (this.settings.showDetailedErrors) { return `${friendlyMsg}${errorMsg}`; } else { return `${friendlyMsg}`; } } async processMathBlock(source, el, ctx) { const blockId = this.generateBlockId(source, ctx.sourcePath); if (this.renderCache.has(blockId)) { el.empty(); const container2 = el.createDiv({ cls: "typst-math-container" }); const cached = this.renderCache.get(blockId); container2.innerHTML = cached != null ? cached : ""; return; } el.empty(); const container = el.createDiv({ cls: "typst-math-container" }); container.innerHTML = '
Rendering with Typst...
'; container.setAttribute("data-typst-blockid", blockId); try { const typstContent = this.wrapInTypstDocument(source); const typstFile = path.join(this.tempDir, `${blockId}.typ`); const htmlFile = path.join(this.tempDir, `${blockId}.html`); this.pendingTypstContent.set(blockId, typstContent); await import_fs.promises.writeFile(typstFile, typstContent, "utf-8"); if (this.settings.useWatchMode) { await this.renderTypstWithWatch(typstFile, htmlFile, container, blockId); } else { await this.renderTypstToHtml(typstFile, htmlFile, container, blockId); } } catch (error) { container.innerHTML = this.formatError(error, false); if (this.settings.debugMode) { console.error("Typst rendering error:", error); } } } renderWithTypst(latex, options) { const isBlock = options.display || false; if (isBlock && !this.settings.enableDisplayMath) { return this.originalTex2chtml(latex, options); } if (!isBlock && !this.settings.enableInlineMath) { return this.originalTex2chtml(latex, options); } if (this.hasLatexCommand(latex)) { } const typstContent = this.convertLatexToTypst(latex); const blockId = this.generateBlockId(typstContent, `math-${Date.now()}`); const container = document.createElement(isBlock ? "div" : "span"); container.className = isBlock ? "typst-math-container" : "typst-math-inline"; container.innerHTML = 'Rendering with Typst...'; try { container.setAttribute("data-typst-blockid", blockId); this.pendingTypstContent.set(blockId, typstContent); } catch (e) { } this.renderTypstMath(typstContent, container, blockId, isBlock); return container; } hasLatexCommand(expr) { return false; } convertLatexToTypst(latex) { let content = latex.trim(); content = content.replace(/^\$\$/, "").replace(/\$\$$/, ""); content = content.replace(/^\$/, "").replace(/\$$/, ""); const conversions = [ // Fractions [/\\frac\{([^}]+)\}\{([^}]+)\}/g, "($1)/($2)"], // Superscripts and subscripts (already mostly compatible) // Greek letters (mostly the same, just remove backslash) [/\\alpha\b/g, "alpha"], [/\\beta\b/g, "beta"], [/\\gamma\b/g, "gamma"], [/\\delta\b/g, "delta"], [/\\epsilon\b/g, "epsilon"], [/\\zeta\b/g, "zeta"], [/\\eta\b/g, "eta"], [/\\theta\b/g, "theta"], [/\\iota\b/g, "iota"], [/\\kappa\b/g, "kappa"], [/\\lambda\b/g, "lambda"], [/\\mu\b/g, "mu"], [/\\nu\b/g, "nu"], [/\\xi\b/g, "xi"], [/\\pi\b/g, "pi"], [/\\rho\b/g, "rho"], [/\\sigma\b/g, "sigma"], [/\\tau\b/g, "tau"], [/\\phi\b/g, "phi"], [/\\chi\b/g, "chi"], [/\\psi\b/g, "psi"], [/\\omega\b/g, "omega"], // Capital Greek [/\\Gamma\b/g, "Gamma"], [/\\Delta\b/g, "Delta"], [/\\Theta\b/g, "Theta"], [/\\Lambda\b/g, "Lambda"], [/\\Xi\b/g, "Xi"], [/\\Pi\b/g, "Pi"], [/\\Sigma\b/g, "Sigma"], [/\\Phi\b/g, "Phi"], [/\\Psi\b/g, "Psi"], [/\\Omega\b/g, "Omega"], // Common functions [/\\sin\b/g, "sin"], [/\\cos\b/g, "cos"], [/\\tan\b/g, "tan"], [/\\log\b/g, "log"], [/\\ln\b/g, "ln"], [/\\exp\b/g, "exp"], // Sums and integrals [/\\sum/g, "sum"], [/\\prod/g, "product"], [/\\int/g, "integral"], [/\\infty\b/g, "oo"], // Arrows [/\\rightarrow\b/g, "->"], [/\\leftarrow\b/g, "<-"], [/\\Rightarrow\b/g, "=>"], [/\\Leftarrow\b/g, "<="], // Operators [/\\times\b/g, "times"], [/\\cdot\b/g, "dot"], [/\\pm\b/g, "plus.minus"], [/\\mp\b/g, "minus.plus"], // Special sets [/\\mathbb\{R\}/g, "RR"], [/\\mathbb\{N\}/g, "NN"], [/\\mathbb\{Z\}/g, "ZZ"], [/\\mathbb\{Q\}/g, "QQ"], [/\\mathbb\{C\}/g, "CC"], // Limits [/\\lim/g, "lim"], [/\\to\b/g, "->"], // Parentheses (mostly the same) [/\\left\(/g, "("], [/\\right\)/g, ")"], [/\\left\[/g, "["], [/\\right\]/g, "]"], [/\\left\{/g, "{"], [/\\right\}/g, "}"], // Sqrt [/\\sqrt\{([^}]+)\}/g, "sqrt($1)"], // Text [/\\text\{([^}]+)\}/g, '"$1"'] ]; for (const [pattern, replacement] of conversions) { content = content.replace(pattern, replacement); } return content.trim(); } async renderTypstMath(mathContent, container, blockId, isBlock) { if (this.renderCache.has(blockId)) { container.innerHTML = this.renderCache.get(blockId); return; } try { const wrappedContent = `$ ${mathContent} $`; const typstContent = this.wrapInTypstDocument(wrappedContent, isBlock); const typstFile = path.join(this.tempDir, `${blockId}.typ`); const htmlFile = path.join(this.tempDir, `${blockId}.html`); this.pendingTypstContent.set(blockId, typstContent); await import_fs.promises.writeFile(typstFile, typstContent, "utf-8"); await this.renderTypstToHtml(typstFile, htmlFile, container, blockId); } catch (error) { container.innerHTML = this.formatError(error, true); if (this.settings.debugMode) { console.error("Typst rendering error:", error); } } } // Synchronously compile a single block (used by prepareExport) async syncCompileBlock(blockId) { try { const typstContent = this.pendingTypstContent.get(blockId); if (!typstContent) return; const typstFile = path.join(this.tempDir, `${blockId}.typ`); const htmlFile = path.join(this.tempDir, `${blockId}.html`); (0, import_fs.writeFileSync)(typstFile, typstContent, "utf-8"); const args = [ "compile", typstFile, htmlFile, "--features", "html", "--format", "html" ]; if (this.settings.debugMode) { console.log("Typst sync compile (prepareExport):", this.settings.typstPath, args.join(" ")); } const res = (0, import_child_process.spawnSync)(this.settings.typstPath, args, { encoding: "utf-8" }); if (res.error || res.status !== 0) { const errStr = res.stderr || res.error && res.error.message || `Typst exited ${res.status}`; throw new Error(errStr); } const html = (0, import_fs.readFileSync)(htmlFile, "utf-8"); const bodyMatch = html.match(/]*>([\s\S]*)<\/body>/i); const content = bodyMatch ? bodyMatch[1] : html; this.renderCache.set(blockId, content); try { const el = document.querySelector(`[data-typst-blockid="${blockId}"]`); if (el instanceof HTMLElement) el.innerHTML = content; } catch (e) { } } catch (error) { if (this.settings.debugMode) console.error("Error in syncCompileBlock:", error); throw error; } } // Prepare the document for export by sync-compiling all pending Typst blocks async prepareExport() { const pending = Array.from(this.pendingTypstContent.keys()); if (pending.length === 0) { new import_obsidian.Notice("No pending Typst math blocks to prepare"); return; } new import_obsidian.Notice(`Preparing ${pending.length} Typst math blocks for export...`); const prevForce = this.settings.forceSyncCompile; const prevSyncOnly = this.settings.syncOnlyDuringExport; this.settings.forceSyncCompile = true; this.settings.syncOnlyDuringExport = false; this.exportInProgress = true; let success = 0; for (const id of pending) { try { await this.syncCompileBlock(id); success++; } catch (e) { console.error("prepareExport: failed to compile block", id, e); } } this.settings.forceSyncCompile = prevForce; this.settings.syncOnlyDuringExport = prevSyncOnly; this.exportInProgress = false; new import_obsidian.Notice(`Prepared ${success}/${pending.length} Typst math blocks for export`); } wrapInTypstDocument(mathContent, isBlock = true) { const sizeConfig = isBlock ? "16pt" : "14pt"; return ` #set text(size: ${sizeConfig}) #show math.equation: html.frame #show math.equation.where(block: false): box ${mathContent} `; } generateBlockId(source, sourcePath) { const hash = this.simpleHash(source + sourcePath); return `block-${hash}`; } simpleHash(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = (hash << 5) - hash + char; hash = hash & hash; } return Math.abs(hash).toString(36); } /** * Parse the full Typst-generated HTML and return a cleaned HTML string. * - Merges paginated pages if present * - Removes placeholder ellipsis-only nodes * - Strips scripts/styles that could interfere */ parseTypstHtml(html) { try { const parser = new DOMParser(); const doc = parser.parseFromString(html, "text/html"); doc.querySelectorAll("script, style").forEach((n) => n.remove()); const pageSelectors = [".typst-page", ".page", ".typst-doc", "#content", "body > div"]; let parts = []; const typstDoc = doc.querySelector(".typst-doc"); if (typstDoc) { const children = Array.from(typstDoc.children); if (children.length > 1) { for (const c of children) parts.push(c.innerHTML); } else { parts.push(typstDoc.innerHTML); } } else { for (const sel of pageSelectors) { const nodes = Array.from(doc.querySelectorAll(sel)); if (nodes.length > 1) { for (const n of nodes) parts.push(n.innerHTML); break; } else if (nodes.length === 1 && parts.length === 0) { parts.push(nodes[0].innerHTML); } } } if (parts.length === 0) { const bodyHtml = doc.body ? doc.body.innerHTML : html; parts = [bodyHtml]; } parts = parts.map((p) => { var _a; const partDoc = parser.parseFromString(`
${p}
`, "text/html"); const walker = document.createTreeWalker(partDoc.body, NodeFilter.SHOW_ELEMENT, null); const toRemove = []; let node = walker.nextNode(); while (node) { const el = node; const txt = (_a = el.textContent) == null ? void 0 : _a.trim(); if (txt && (/^\.{3,}$/.test(txt) || /^…+$/.test(txt) || txt === "\u22EF")) { toRemove.push(el); } node = walker.nextNode(); } toRemove.forEach((e) => e.remove()); return partDoc.body.innerHTML; }); const joined = parts.map((p, i) => `
${p}
`).join('\n
\n'); return joined; } catch (e) { return html; } } async renderTypstToHtml(typstFile, htmlFile, container, blockId) { const useSync = this.settings.forceSyncCompile || this.settings.syncOnlyDuringExport && this.exportInProgress; if (useSync) { try { const args = [ "compile", typstFile, htmlFile, "--features", "html", "--format", "html" ]; if (this.settings.debugMode) { console.log("Running Typst (sync):", this.settings.typstPath, args.join(" ")); } const res = (0, import_child_process.spawnSync)(this.settings.typstPath, args, { encoding: "utf-8" }); if (res.error) { const errMsg = res.error.message || String(res.error); container.innerHTML = this.formatError(errMsg, false); throw res.error; } if (res.status !== 0) { const errStr = res.stderr || `Typst process exited with code ${res.status}`; container.innerHTML = this.formatError(errStr, false); throw new Error(errStr); } const html = (0, import_fs.readFileSync)(htmlFile, "utf-8"); const bodyMatch = html.match(/]*>([\s\S]*)<\/body>/i); const content = bodyMatch ? bodyMatch[1] : html; this.renderCache.set(blockId, content); container.innerHTML = content; return Promise.resolve(); } catch (err) { if (this.settings.debugMode) console.error("Typst sync render error:", err); return Promise.reject(err); } } return new Promise((resolve, reject) => { var _a; if (this.watchers.has(blockId)) { (_a = this.watchers.get(blockId)) == null ? void 0 : _a.kill(); this.watchers.delete(blockId); } const args = [ "compile", typstFile, htmlFile, "--features", "html", "--format", "html" ]; if (this.settings.debugMode) { console.log( "Running Typst command:", this.settings.typstPath, args.join(" ") ); } const typstProcess = (0, import_child_process.spawn)(this.settings.typstPath, args); let stderr = ""; typstProcess.stderr.on("data", (data) => { stderr += data.toString(); }); typstProcess.on("close", async (code) => { if (code === 0) { try { const html = await import_fs.promises.readFile(htmlFile, "utf-8"); const bodyMatch = html.match(/]*>([\s\S]*)<\/body>/i); const content = bodyMatch ? bodyMatch[1] : html; this.renderCache.set(blockId, content); container.innerHTML = content; resolve(); } catch (error) { container.innerHTML = this.formatError(error, false); reject(error); } } else { const errorMsg = stderr || `Typst process exited with code ${code}`; container.innerHTML = this.formatError(errorMsg, false); reject(new Error(errorMsg)); } }); typstProcess.on("error", (error) => { container.innerHTML = this.formatError(error, false); reject(error); }); }); } async renderTypstWithWatch(typstFile, htmlFile, container, blockId) { return new Promise((resolve, reject) => { var _a; if (this.watchers.has(blockId)) { (_a = this.watchers.get(blockId)) == null ? void 0 : _a.kill(); this.watchers.delete(blockId); } const args = [ "watch", typstFile, htmlFile, "--features", "html", "--format", "html" ]; if (this.settings.debugMode) { console.log( "Running Typst watch:", this.settings.typstPath, args.join(" ") ); } const typstProcess = (0, import_child_process.spawn)(this.settings.typstPath, args); this.watchers.set(blockId, typstProcess); let stderr = ""; let hasRendered = false; const checkForUpdates = async () => { try { const html = await import_fs.promises.readFile(htmlFile, "utf-8"); const bodyMatch = html.match(/]*>([\s\S]*)<\/body>/i); const content = bodyMatch ? bodyMatch[1] : html; this.renderCache.set(blockId, content); container.innerHTML = content; if (!hasRendered) { hasRendered = true; resolve(); } } catch (error) { if (this.settings.debugMode) { console.log("Waiting for Typst to generate output..."); } } }; typstProcess.stderr.on("data", (data) => { stderr += data.toString(); if (stderr.includes("error:")) { container.innerHTML = this.formatError(stderr, false); } }); typstProcess.stdout.on("data", (data) => { const output = data.toString(); if (this.settings.debugMode) { console.log("Typst watch output:", output); } if (output.includes("written to") || output.includes("compiled")) { setTimeout(checkForUpdates, 100); } }); setTimeout(checkForUpdates, 500); typstProcess.on("close", (code) => { this.watchers.delete(blockId); if (code !== 0 && code !== null && !hasRendered) { const errorMsg = stderr || `Typst watch exited with code ${code}`; container.innerHTML = this.formatError(errorMsg, false); reject(new Error(errorMsg)); } }); typstProcess.on("error", (error) => { this.watchers.delete(blockId); container.innerHTML = this.formatError(error, false); reject(error); }); }); } }; var TypstMathSettingTab = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { const { containerEl } = this; containerEl.empty(); containerEl.createEl("h2", { text: "Typst Math Renderer Settings" }); new import_obsidian.Setting(containerEl).setName("Typst CLI path").setDesc('Path to the Typst executable (e.g., "typst" or full path)').addText( (text) => text.setPlaceholder("typst").setValue(this.plugin.settings.typstPath).onChange(async (value) => { this.plugin.settings.typstPath = value; await this.plugin.saveSettings(); }) ); new import_obsidian.Setting(containerEl).setName("Enable inline math").setDesc("Process inline math blocks ($...$)").addToggle( (toggle) => toggle.setValue(this.plugin.settings.enableInlineMath).onChange(async (value) => { this.plugin.settings.enableInlineMath = value; await this.plugin.saveSettings(); }) ); new import_obsidian.Setting(containerEl).setName("Enable display math").setDesc("Process display math blocks ($$...$$)").addToggle( (toggle) => toggle.setValue(this.plugin.settings.enableDisplayMath).onChange(async (value) => { this.plugin.settings.enableDisplayMath = value; await this.plugin.saveSettings(); }) ); new import_obsidian.Setting(containerEl).setName("Debug mode").setDesc("Enable debug logging in the console").addToggle( (toggle) => toggle.setValue(this.plugin.settings.debugMode).onChange(async (value) => { this.plugin.settings.debugMode = value; await this.plugin.saveSettings(); }) ); new import_obsidian.Setting(containerEl).setName("Show detailed errors").setDesc("Display detailed Typst error messages (useful for debugging)").addToggle( (toggle) => toggle.setValue(this.plugin.settings.showDetailedErrors).onChange(async (value) => { this.plugin.settings.showDetailedErrors = value; await this.plugin.saveSettings(); }) ); new import_obsidian.Setting(containerEl).setName("Use watch mode").setDesc("Enable watch mode for code blocks (auto-recompile on changes) - experimental").addToggle( (toggle) => toggle.setValue(this.plugin.settings.useWatchMode).onChange(async (value) => { this.plugin.settings.useWatchMode = value; await this.plugin.saveSettings(); }) ); new import_obsidian.Setting(containerEl).setName("Force synchronous compile (for exports)").setDesc("Use a synchronous Typst compile which can improve reliability when exporting to PDF. This will block rendering while Typst runs.").addToggle( (toggle) => toggle.setValue(this.plugin.settings.forceSyncCompile).onChange(async (value) => { this.plugin.settings.forceSyncCompile = value; await this.plugin.saveSettings(); new import_obsidian.Notice("Force sync compile setting updated"); }) ); new import_obsidian.Setting(containerEl).setName("Sync only during print/export").setDesc("If enabled, synchronous compilation will only be used during a print/export flow. Disable to always use sync compilation when enabled.").addToggle( (toggle) => toggle.setValue(this.plugin.settings.syncOnlyDuringExport).onChange(async (value) => { this.plugin.settings.syncOnlyDuringExport = value; await this.plugin.saveSettings(); new import_obsidian.Notice("Sync-only-during-export setting updated"); }) ); new import_obsidian.Setting(containerEl).setName("Enable live preview").setDesc("Render Typst math in live preview mode (works automatically via MathJax override)").addToggle( (toggle) => toggle.setValue(this.plugin.settings.enableLivePreview).onChange(async (value) => { this.plugin.settings.enableLivePreview = value; await this.plugin.saveSettings(); new import_obsidian.Notice("Reload Obsidian for this change to take full effect"); }) ); containerEl.createEl("h3", { text: "Usage" }); containerEl.createEl("p", { text: "Create a code block with ```math or ```typst and write your Typst math syntax inside." }); containerEl.createEl("pre", { text: "```math\n$ sum_(i=1)^n i = (n(n+1))/2 $\n```" }); containerEl.createEl("h3", { text: "Installation" }); containerEl.createEl("p", { text: "Make sure you have Typst CLI installed. Visit https://github.com/typst/typst for installation instructions." }); } };