diff --git a/.eleventy.js b/.eleventy.js
index 2c381874e..b5717efb2 100644
--- a/.eleventy.js
+++ b/.eleventy.js
@@ -202,6 +202,11 @@ module.exports = function (eleventyConfig) {
)}`;
return res
}
+ if (token.info === "tikz") {
+ const code = token.content.trim();
+ const b64 = Buffer.from(code, "utf8").toString("base64"); // Encode into Base64 to avoid issues with special characters in TeX code
+ return `
${b64}
`;
+ }
// Other languages
return origFenceRule(tokens, idx, options, env, slf);
@@ -501,6 +506,81 @@ module.exports = function (eleventyConfig) {
return str && parsed.innerHTML;
});
+ eleventyConfig.addTransform("render-tikzjax", (() => {
+ // Lazy loading to save resources.
+ const tex2svg = require("node-tikzjax").default;
+
+ // Serialize renderings.
+ // Running node-tikzjax instances concurrently is problematic. See: https://github.com/prinsss/node-tikzjax/blob/main/README.md
+ let tikzQueue = Promise.resolve();
+
+ // https://github.com/artisticat1/obsidian-tikzjax/blob/main/main.ts
+ function tidyTikzSource(src) {
+ if (!src) return src;
+ return src
+ .replaceAll(" ", "") // Remove non-breaking space characters, otherwise we get errors
+ .replace(/\u00A0/g, "")
+ .replace(/\r\n/g, "\n") // Normalize line endings & Split into lines
+ .split("\n")
+ .map((line) => line.trim()) // Trim whitespace that is inserted when pasting in code, otherwise TikZJax complains
+ .filter((line) => line.length > 0) // Remove empty lines
+ .join("\n");
+ }
+
+ return async function (content, outputPath) {
+ if (!outputPath || !outputPath.endsWith(".html")) return content;
+ if (!content || !content.includes('class="block-language-tikz"')) return content;
+
+ const root = parse(content);
+ const blocks = root.querySelectorAll("div.block-language-tikz");
+ if (!blocks.length) return content;
+
+ for (const block of blocks) {
+ const srcB64 = block.text || "";
+ const texSource = tidyTikzSource(Buffer.from(srcB64, "base64").toString("utf8"));
+ try {
+ const run = tikzQueue
+ .catch(() => {})
+ .then(() =>
+ tex2svg(texSource, {
+ // SvgOptions
+ embedFontCss: true, // Whether to embed the font CSS file in the SVG.
+ // TeXOptions
+ showConsole: false, // Print log of TeX engine to console.
+ texPackages: {}, // Additional TeX packages to load. e.g. texPackages: { pgfplots: '', amsmath: 'intlimits' },
+ tikzLibraries: '', // Additional TikZ libraries to load. e.g. tikzLibraries: 'arrows.meta,calc'
+ })
+ );
+ tikzQueue = run.catch(() => {});
+ const svg = await run;
+
+ const svgElement = parse(svg)
+ .querySelector("svg");
+ if (svgElement) {
+ // Zooming would result in other TikZ diagrams being overlapped or partly invisible.
+ svgElement.setAttribute("style", "margin:auto; display:block;"); // e.g. oleeskild/obsidian-digital-garden#667
+ block.replaceWith(svgElement);
+ }
+ } catch (e) {
+ console.warn("\n[TikZJax] render failed at:", outputPath);
+ console.warn("[TikZJax] TeX source (first 400 chars):\n", texSource.slice(0, 400));
+ console.warn("[TikZJax] Warn:", e);
+ // Escape texSource to be interpreted as HTML properly.
+ // https://stackoverflow.com/a/7382028
+ const texSource_escaped = texSource
+ .replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll('"', """)
+ .replaceAll("'", "'");
+ block.replaceWith(`TikZ render failed. See build log.\n\n${(texSource_escaped)}
`);
+ }
+ }
+
+ return root.toString();
+ };
+ })());
+
eleventyConfig.addTransform("htmlMinifier", async (content, outputPath) => {
if (
(process.env.NODE_ENV === "production" || process.env.ELEVENTY_ENV === "prod") &&
diff --git a/package-lock.json b/package-lock.json
index 995776466..2a604ae94 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,6 +26,7 @@
"markdown-it-mathjax3": "^4.3.1",
"markdown-it-plantuml": "^1.4.1",
"markdown-it-task-checkbox": "^1.0.6",
+ "node-tikzjax": "^1.0.5",
"npm-run-all": "^4.1.5",
"rimraf": "^4.4.1"
},
diff --git a/package.json b/package.json
index 584bbd56d..119d2e6fc 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"markdown-it-mathjax3": "^4.3.1",
"markdown-it-plantuml": "^1.4.1",
"markdown-it-task-checkbox": "^1.0.6",
+ "node-tikzjax": "^1.0.5",
"npm-run-all": "^4.1.5",
"rimraf": "^4.4.1"
}