2021-08-04 01:55:39 +02:00
|
|
|
// Copyright: Ankitects Pty Ltd and contributors
|
|
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
|
2021-09-17 21:30:32 +02:00
|
|
|
/* eslint
|
|
|
|
@typescript-eslint/no-explicit-any: "off",
|
|
|
|
*/
|
|
|
|
|
2021-08-07 05:46:52 +02:00
|
|
|
import { mathIcon } from "./icons";
|
|
|
|
|
|
|
|
const parser = new DOMParser();
|
2021-08-04 18:57:34 +02:00
|
|
|
|
2021-08-07 22:07:57 +02:00
|
|
|
function getCSS(nightMode: boolean, fontSize: number): string {
|
2021-08-07 21:03:36 +02:00
|
|
|
const color = nightMode ? "white" : "black";
|
2021-08-07 20:26:39 +02:00
|
|
|
/* color is set for Maths, fill for the empty icon */
|
2021-08-07 22:52:48 +02:00
|
|
|
return `svg { color: ${color}; fill: ${color}; font-size: ${fontSize}px; };`;
|
2021-08-07 22:07:57 +02:00
|
|
|
}
|
2021-08-07 05:46:52 +02:00
|
|
|
|
2021-08-07 22:07:57 +02:00
|
|
|
function getStyle(css: string): HTMLStyleElement {
|
|
|
|
const style = document.createElement("style") as HTMLStyleElement;
|
|
|
|
style.appendChild(document.createTextNode(css));
|
|
|
|
return style;
|
|
|
|
}
|
2021-08-04 01:55:39 +02:00
|
|
|
|
2021-08-07 22:07:57 +02:00
|
|
|
function getEmptyIcon(style: HTMLStyleElement): [string, string] {
|
2021-08-07 05:46:52 +02:00
|
|
|
const icon = parser.parseFromString(mathIcon, "image/svg+xml");
|
|
|
|
const svg = icon.children[0];
|
2021-08-04 18:57:34 +02:00
|
|
|
svg.insertBefore(style, svg.children[0]);
|
2021-08-07 05:46:52 +02:00
|
|
|
|
2021-08-07 22:23:18 +02:00
|
|
|
return [svg.outerHTML, "MathJax"];
|
2021-08-04 01:55:39 +02:00
|
|
|
}
|
2021-08-07 05:46:52 +02:00
|
|
|
|
2021-08-07 21:03:36 +02:00
|
|
|
export function convertMathjax(
|
|
|
|
input: string,
|
|
|
|
nightMode: boolean,
|
2021-10-19 01:06:00 +02:00
|
|
|
fontSize: number,
|
2021-08-07 21:03:36 +02:00
|
|
|
): [string, string] {
|
2021-08-07 22:07:57 +02:00
|
|
|
const style = getStyle(getCSS(nightMode, fontSize));
|
|
|
|
|
2021-08-07 05:46:52 +02:00
|
|
|
if (input.trim().length === 0) {
|
2021-08-07 22:07:57 +02:00
|
|
|
return getEmptyIcon(style);
|
2021-08-07 05:46:52 +02:00
|
|
|
}
|
|
|
|
|
2021-09-16 14:31:20 +02:00
|
|
|
let output: Element;
|
|
|
|
try {
|
|
|
|
output = globalThis.MathJax.tex2svg(input);
|
|
|
|
} catch (e) {
|
|
|
|
return ["Mathjax Error", String(e)];
|
|
|
|
}
|
|
|
|
|
|
|
|
const svg = output.children[0] as SVGElement;
|
2021-08-07 05:46:52 +02:00
|
|
|
|
2021-09-16 14:31:20 +02:00
|
|
|
if ((svg as any).viewBox.baseVal.height === 16) {
|
2021-08-07 22:07:57 +02:00
|
|
|
return getEmptyIcon(style);
|
2021-08-07 05:46:52 +02:00
|
|
|
}
|
|
|
|
|
2021-08-07 19:33:01 +02:00
|
|
|
let title = "";
|
|
|
|
|
2021-08-07 19:13:08 +02:00
|
|
|
if (svg.innerHTML.includes("data-mjx-error")) {
|
2021-09-16 14:31:20 +02:00
|
|
|
svg.querySelector("rect")?.setAttribute("fill", "yellow");
|
|
|
|
svg.querySelector("text")?.setAttribute("color", "red");
|
|
|
|
title = svg.querySelector("title")?.innerHTML ?? "";
|
2021-08-07 19:13:08 +02:00
|
|
|
} else {
|
2021-08-07 05:46:52 +02:00
|
|
|
svg.insertBefore(style, svg.children[0]);
|
|
|
|
}
|
2021-08-07 19:13:08 +02:00
|
|
|
|
2021-08-07 19:33:01 +02:00
|
|
|
return [svg.outerHTML, title];
|
2021-08-07 05:46:52 +02:00
|
|
|
}
|
2022-04-25 05:42:54 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Escape characters which are technically legal in Mathjax, but confuse HTML.
|
|
|
|
*/
|
|
|
|
export function escapeSomeEntities(value: string): string {
|
|
|
|
return value.replace(/</g, "<").replace(/>/g, ">");
|
|
|
|
}
|
|
|
|
|
|
|
|
export function unescapeSomeEntities(value: string): string {
|
|
|
|
return value.replace(/</g, "<").replace(/>/g, ">");
|
|
|
|
}
|