fix(markdown): load TikZ font stylesheet to keep text aligned

The obsidian-tikzjax bundle emits SVG referencing Computer Modern font
families like cmbx7 but ships the @font-face declarations in a separate
styles.css. Without it the browser substitutes a default font whose
glyph widths don't match TeX's, leaving visible gaps between each
kerned text run. Lazy-load the stylesheet alongside the engine on
first TikZ render so cache hits and misses both see correct fonts.
This commit is contained in:
Julien Calixte
2026-05-15 16:25:55 +02:00
parent 33285d723a
commit 572a05962c

View File

@@ -28,6 +28,8 @@ import { markdownItTablerIcons } from "@/utils/markdown/markdown-it-tabler-icons
const TIKZ_BUNDLE_URL = const TIKZ_BUNDLE_URL =
"https://cdn.jsdelivr.net/gh/artisticat1/obsidian-tikzjax@0.5.2/tikzjax.js" "https://cdn.jsdelivr.net/gh/artisticat1/obsidian-tikzjax@0.5.2/tikzjax.js"
const TIKZ_STYLES_URL =
"https://cdn.jsdelivr.net/gh/artisticat1/obsidian-tikzjax@0.5.2/styles.css"
const TIKZ_RENDER_TIMEOUT_MS = 30000 const TIKZ_RENDER_TIMEOUT_MS = 30000
const markdownItMermaidExtractor = (md: MarkdownIt) => { const markdownItMermaidExtractor = (md: MarkdownIt) => {
@@ -188,6 +190,7 @@ export const runMermaid = (querySelector: string) => {
} }
let tikzBundlePromise: Promise<void> | null = null let tikzBundlePromise: Promise<void> | null = null
let tikzStylesPromise: Promise<void> | null = null
let domPurifyPromise: Promise<typeof import("dompurify")> | null = null let domPurifyPromise: Promise<typeof import("dompurify")> | null = null
const ensureTikzBundle = (): Promise<void> => { const ensureTikzBundle = (): Promise<void> => {
@@ -215,6 +218,31 @@ const ensureTikzBundle = (): Promise<void> => {
return tikzBundlePromise return tikzBundlePromise
} }
const ensureTikzStyles = (): Promise<void> => {
if (tikzStylesPromise) return tikzStylesPromise
tikzStylesPromise = new Promise<void>((resolve, reject) => {
const existing = document.getElementById("tikzjax-styles")
if (existing) {
resolve()
return
}
const link = document.createElement("link")
link.id = "tikzjax-styles"
link.rel = "stylesheet"
link.href = TIKZ_STYLES_URL
link.crossOrigin = "anonymous"
link.addEventListener("load", () => resolve())
link.addEventListener("error", () => {
tikzStylesPromise = null
reject(new Error("Failed to load TikZ font styles"))
})
document.head.appendChild(link)
})
return tikzStylesPromise
}
const ensureDomPurify = (): Promise<typeof import("dompurify")> => { const ensureDomPurify = (): Promise<typeof import("dompurify")> => {
if (!domPurifyPromise) domPurifyPromise = import("dompurify") if (!domPurifyPromise) domPurifyPromise = import("dompurify")
return domPurifyPromise return domPurifyPromise
@@ -297,6 +325,8 @@ export const runTikz = async (querySelector: string): Promise<void> => {
) )
if (elements.length === 0) return if (elements.length === 0) return
void ensureTikzStyles().catch(() => undefined)
await Promise.all( await Promise.all(
elements.map(async (el) => { elements.map(async (el) => {
if (el.dataset.tikzRendered) return if (el.dataset.tikzRendered) return