diff --git a/src/elements/markdown/math.mjs b/src/elements/markdown/math.mjs index 745880b..7403d8f 100644 --- a/src/elements/markdown/math.mjs +++ b/src/elements/markdown/math.mjs @@ -1,5 +1,7 @@ import {CustomElement} from "../base.mjs"; import {default as katex} from 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.mjs'; +import { MarkdownElement } from "./renderer.mjs"; +import { findFirstAncestor } from "../../utils/traversal.mjs"; /** * Element rendering TeX math. @@ -9,6 +11,21 @@ export class MathElement extends CustomElement { return document.getElementById("template-math") } + /** + * Element representing the Markdown context where this math formula is displayed in. + * Can be recalculated with {@link recalculateRenderer}. + * @type {MarkdownElement} + */ + renderer + + /** + * Recalculate the value of {@link browse} and {@link vault} using this element's current position in the DOM. + * @returns {void} + */ + recalculateRenderer() { + this.renderer = findFirstAncestor(this, MarkdownElement) + } + /** * The math to render, obtained from the `document` attribute. * @returns {string} @@ -42,12 +59,6 @@ export class MathElement extends CustomElement { */ katexElement - /** - * The group to use to store macros in. - * Should be overridden by the creator element. - */ - katexMacros = {} - /** * The name of the slot where {@link katexElement} should be placed in. * @type {string} @@ -57,7 +68,7 @@ export class MathElement extends CustomElement { /** * Recreate {@link katexElement} with the current values of {@link texDocument} and {@link isBlock}. */ - recreateKatexElement() { + async recreateKatexElement() { if(this.katexElement) { this.katexElement.remove() this.katexElement = null @@ -68,13 +79,15 @@ export class MathElement extends CustomElement { this.katexElement.classList.add("math") this.katexElement.classList.add(this.isBlock ? "math-block" : "math-inline") + await this.renderer.sleepUntilKatexMacrosAreAvailable() + katex.render( this.texDocument, this.katexElement, { throwOnError: false, globalGroup: true, - macros: this.katexMacros, + macros: this.renderer.katexMacros, trust: true, } ) @@ -84,6 +97,7 @@ export class MathElement extends CustomElement { onConnect() { super.onConnect() + this.recalculateRenderer() this.recreateKatexElement() } } diff --git a/src/elements/markdown/renderer.mjs b/src/elements/markdown/renderer.mjs index f5abe50..e8d01b2 100644 --- a/src/elements/markdown/renderer.mjs +++ b/src/elements/markdown/renderer.mjs @@ -15,7 +15,7 @@ export class MarkdownElement extends CustomElement { /** * Element representing the Obsidian Vault. - * Can be recalculated with {@link recalculateAncestors}. + * Can be recalculated with {@link recalculateVault}. * @type {VaultElement} */ vault @@ -24,15 +24,10 @@ export class MarkdownElement extends CustomElement { * Recalculate the value of {@link browse} and {@link vault} using this element's current position in the DOM. * @returns {void} */ - recalculateAncestors() { + recalculateVault() { this.vault = findFirstAncestor(this, VaultElement) } - /** - * The group to use to store KaTeX macros in for everything in this {@link MarkdownElement}. - */ - katexGroup - // noinspection JSUnusedGlobalSymbols /** * {@link Marked} Markdown renderer. @@ -236,10 +231,42 @@ export class MarkdownElement extends CustomElement { */ static DOCUMENT_ELEMENT_SLOT = "markdown-document" + /** + * Macros to be used in every single {@link MathElement} of the renderer. + */ + katexMacros + + /** + * Update {@link katexMacros} from the root {@link VaultElement}. + * @returns {Promise} + */ + async refetchKatexMacros() { + await this.vault.sleepUntilKatexMacrosAreAvailable() + this.katexMacros = {...this.vault.katexMacros} + 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)) + } + /** * Recreate {@link documentElement} using the current value of {@link markdownDocument}. */ - async recreateDocumentElement() { + recreateDocumentElement() { if(this.documentElement) { this.documentElement.remove() this.documentElement = null @@ -249,19 +276,13 @@ 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.katexMacros = this.katexMacros - } - this.appendChild(this.documentElement) } onConnect() { super.onConnect() - this.recalculateAncestors() - this.recreateDocumentElement().then() + this.recalculateVault() + this.recreateDocumentElement() + this.refetchKatexMacros().then() } } diff --git a/src/elements/vault.mjs b/src/elements/vault.mjs index 3fd2b25..7c9ac1d 100644 --- a/src/elements/vault.mjs +++ b/src/elements/vault.mjs @@ -231,12 +231,12 @@ export class VaultElement extends CustomElement { await new Promise(resolve => this.#katexMacrosQueue.push(resolve)) } - async onConnect() { + onConnect() { super.onConnect() this.recalculateVaultElement() this.#fetchQueueScheduler().then() - await this.refetchAppearance() - await this.refetchFileIndex() - await this.refetchKatexMacros() + this.refetchAppearance().then() + this.refetchFileIndex().then() + this.refetchKatexMacros().then() } } \ No newline at end of file