From 069b36c20d25bd3c2d03b416d45cf2a3e6a3405b Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 8 Nov 2024 06:38:00 +0100 Subject: [PATCH] Use katex preamble --- src/elements/markdown/math.mjs | 5 ++-- src/elements/markdown/renderer.mjs | 29 ++++++++++++++++--- src/elements/vault.mjs | 46 ++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/elements/markdown/math.mjs b/src/elements/markdown/math.mjs index 982f9d6..745880b 100644 --- a/src/elements/markdown/math.mjs +++ b/src/elements/markdown/math.mjs @@ -46,7 +46,7 @@ export class MathElement extends CustomElement { * The group to use to store macros in. * Should be overridden by the creator element. */ - katexGroup = {} + katexMacros = {} /** * The name of the slot where {@link katexElement} should be placed in. @@ -74,7 +74,7 @@ export class MathElement extends CustomElement { { throwOnError: false, globalGroup: true, - macros: this.katexGroup, + macros: this.katexMacros, trust: true, } ) @@ -84,7 +84,6 @@ export class MathElement extends CustomElement { onConnect() { super.onConnect() - this.recreateKatexElement() } } diff --git a/src/elements/markdown/renderer.mjs b/src/elements/markdown/renderer.mjs index 973a522..f5abe50 100644 --- a/src/elements/markdown/renderer.mjs +++ b/src/elements/markdown/renderer.mjs @@ -1,6 +1,8 @@ import { Marked } from "https://unpkg.com/marked@9.1.2/lib/marked.esm.js"; import { CustomElement } from "../base.mjs"; import {toTitleCase} from "../../utils/case.mjs"; +import {findFirstAncestor} from "../../utils/traversal.mjs"; +import {VaultElement} from "../vault.mjs"; /** @@ -11,10 +13,25 @@ export class MarkdownElement extends CustomElement { return document.getElementById("template-markdown") } + /** + * Element representing the Obsidian Vault. + * Can be recalculated with {@link recalculateAncestors}. + * @type {VaultElement} + */ + vault + + /** + * Recalculate the value of {@link browse} and {@link vault} using this element's current position in the DOM. + * @returns {void} + */ + recalculateAncestors() { + this.vault = findFirstAncestor(this, VaultElement) + } + /** * The group to use to store KaTeX macros in for everything in this {@link MarkdownElement}. */ - katexGroup = {} + katexGroup // noinspection JSUnusedGlobalSymbols /** @@ -222,7 +239,7 @@ export class MarkdownElement extends CustomElement { /** * Recreate {@link documentElement} using the current value of {@link markdownDocument}. */ - recreateDocumentElement() { + async recreateDocumentElement() { if(this.documentElement) { this.documentElement.remove() this.documentElement = null @@ -232,8 +249,11 @@ export class MarkdownElement extends CustomElement { this.documentElement.slot = this.constructor.DOCUMENT_ELEMENT_SLOT this.documentElement.innerHTML = this.constructor.MARKED.parse(this.markdownDocument) + // TODO: await this properly + await this.vault.sleepUntilKatexMacrosAreAvailable() + this.katexMacros = {...this.vault.katexMacros} for(const el of this.documentElement.getElementsByTagName("x-math")) { - el.katexGroup = this.katexGroup + el.katexMacros = this.katexMacros } this.appendChild(this.documentElement) @@ -241,6 +261,7 @@ export class MarkdownElement extends CustomElement { onConnect() { super.onConnect() - this.recreateDocumentElement() + this.recalculateAncestors() + this.recreateDocumentElement().then() } } diff --git a/src/elements/vault.mjs b/src/elements/vault.mjs index e7d1a63..3fd2b25 100644 --- a/src/elements/vault.mjs +++ b/src/elements/vault.mjs @@ -1,5 +1,6 @@ import { CustomElement } from "./base.mjs"; import { sleep } from "../utils/sleep.mjs"; +import {default as katex} from 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.mjs'; /** @@ -186,11 +187,56 @@ export class VaultElement extends CustomElement { await new Promise(resolve => this.#fileIndexQueue.push(resolve)) } + /** + * Macros to be used in every single {@link MathElement} of the vault. + */ + katexMacros + + /** + * Update {@link katexMacros} by fetching the `preamble.sty` file located at the root of the Vault, and then having KaTeX render it to a string, which is then discarded. + * @returns {Promise} + */ + async refetchKatexMacros() { + const response = await this.fetchCooldown("preamble.sty") + if(response.status >= 400) { + this.katexMacros = {} + this.#katexMacrosQueue.forEach(resolve => resolve(undefined)) + return + } + const preamble = await response.text() + this.katexMacros = {} + katex.renderToString(preamble, { + throwOnError: false, + globalGroup: true, + macros: this.katexMacros, + trust: true, + }) + this.#katexMacrosQueue.forEach(resolve => resolve(undefined)) + } + + /** + * Array of resolve {@link Promise} objects of tasks awaiting {@link sleepUntilKatexPreambleIsAvailable}. + * @type {((v: undefined) => void)[]} + */ + #katexMacrosQueue = [] + + /** + * Await until {@link katexPreamble} becomes available. + * @returns {Promise} + */ + async sleepUntilKatexMacrosAreAvailable() { + if(this.katexMacros !== undefined) { + return + } + await new Promise(resolve => this.#katexMacrosQueue.push(resolve)) + } + async onConnect() { super.onConnect() this.recalculateVaultElement() this.#fetchQueueScheduler().then() await this.refetchAppearance() await this.refetchFileIndex() + await this.refetchKatexMacros() } } \ No newline at end of file