diff --git a/ts/reviewer/index.ts b/ts/reviewer/index.ts index 63771f0b0..122d365dd 100644 --- a/ts/reviewer/index.ts +++ b/ts/reviewer/index.ts @@ -36,7 +36,7 @@ export function getTypedAnswer(): string | null { return typeans?.value ?? null; } -function _runHook( +export function _runHook( hooks: Array, ): Promise>[]> { const promises: (Promise | void)[] = []; diff --git a/ts/routes/reviewer-inner/index.ts b/ts/routes/reviewer-inner/index.ts index 96fd642aa..ced043adf 100644 --- a/ts/routes/reviewer-inner/index.ts +++ b/ts/routes/reviewer-inner/index.ts @@ -6,7 +6,8 @@ import "../../reviewer/reviewer.scss"; import "../../mathjax"; import "mathjax/es5/tex-chtml-full.js"; -import { renderError } from "../../reviewer"; +import { registerPackage } from "@tslib/runtime-require"; +import { _runHook, renderError } from "../../reviewer"; import { addBrowserClasses } from "../../reviewer/browser_selector"; import { imageOcclusionAPI } from "../image-occlusion/review"; import { enableNightMode } from "../reviewer/reviewer"; @@ -25,6 +26,14 @@ function postParentMessage(message: ReviewerRequest) { ); } +type Callback = () => void | Promise; + +export const onUpdateHook: Array = []; +export const onShownHook: Array = []; + +globalThis.onUpdateHook = onUpdateHook; +globalThis.onShownHook = onShownHook; + declare const MathJax: any; const urlParams = new URLSearchParams(location.search); const decoder = new TextDecoder(); @@ -53,15 +62,8 @@ addEventListener("message", async (e: MessageEvent) => { } } - // wait for mathjax to ready - await MathJax.startup.promise - .then(() => { - // clear MathJax buffers from previous typesets - MathJax.typesetClear(); - - return MathJax.typesetPromise([document.body]); - }) - .catch(renderError("MathJax")); + onUpdateHook.length = 0; + onShownHook.length = 0; // "".innerHTML =" does not run scripts for (const script of document.querySelectorAll("script")) { @@ -74,6 +76,18 @@ addEventListener("message", async (e: MessageEvent) => { parent.appendChild(new_script); } + _runHook(onUpdateHook); + // wait for mathjax to ready + await MathJax.startup.promise + .then(() => { + // clear MathJax buffers from previous typesets + MathJax.typesetClear(); + + return MathJax.typesetPromise([document.body]); + }) + .catch(renderError("MathJax")); + + _runHook(onShownHook); break; } default: { @@ -190,3 +204,13 @@ Object.defineProperty(window, "localStorage", { configurable: true, enumerable: true, }); + +registerPackage("anki/reviewer", { + // If you append a function to this each time the question or answer + // is shown, it will be called before MathJax has been rendered. + onUpdateHook, + // If you append a function to this each time the question or answer + // is shown, it will be called after images have been preloaded and + // MathJax has been rendered. + onShownHook, +});