Instead of transforming to {\lt}, transform to < (#1818)
* Instead of transforming to {\lt}, transform to < - In Mathjax editor - This way you can also use Mathjax convenience shortcuts like <=> in chemistry mode: \ce{<=>} * Remove unused translateEntitiesToMathjax() (dae) https://github.com/ankitects/anki/pull/1818#discussion_r857238310
This commit is contained in:
parent
ee70006ec4
commit
2be1f4c56d
@ -23,13 +23,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import { randomUUID } from "../lib/uuid";
|
||||
import { pageTheme } from "../sveltelib/theme";
|
||||
import { convertMathjax } from "./mathjax";
|
||||
import { convertMathjax, unescapeSomeEntities } from "./mathjax";
|
||||
|
||||
export let mathjax: string;
|
||||
export let block: boolean;
|
||||
export let fontSize: number;
|
||||
|
||||
$: [converted, title] = convertMathjax(mathjax, $pageTheme.isDark, fontSize);
|
||||
$: [converted, title] = convertMathjax(
|
||||
unescapeSomeEntities(mathjax),
|
||||
$pageTheme.isDark,
|
||||
fontSize,
|
||||
);
|
||||
$: empty = title === "MathJax";
|
||||
$: encoded = encodeURIComponent(converted);
|
||||
|
||||
|
@ -15,14 +15,6 @@ const mathjaxTagPattern =
|
||||
const mathjaxBlockDelimiterPattern = /\\\[(.*?)\\\]/gsu;
|
||||
const mathjaxInlineDelimiterPattern = /\\\((.*?)\\\)/gsu;
|
||||
|
||||
/**
|
||||
* If the user enters the Mathjax with delimiters, "<" and ">" will
|
||||
* be first translated to entities.
|
||||
*/
|
||||
function translateEntitiesToMathjax(value: string) {
|
||||
return value.replace(/</g, "{\\lt}").replace(/>/g, "{\\gt}");
|
||||
}
|
||||
|
||||
export const Mathjax: DecoratedElementConstructor = class Mathjax
|
||||
extends HTMLElement
|
||||
implements DecoratedElement
|
||||
@ -45,12 +37,10 @@ export const Mathjax: DecoratedElementConstructor = class Mathjax
|
||||
static toUndecorated(stored: string): string {
|
||||
return stored
|
||||
.replace(mathjaxBlockDelimiterPattern, (_match: string, text: string) => {
|
||||
const escaped = translateEntitiesToMathjax(text);
|
||||
return `<${Mathjax.tagName} block="true">${escaped}</${Mathjax.tagName}>`;
|
||||
return `<${Mathjax.tagName} block="true">${text}</${Mathjax.tagName}>`;
|
||||
})
|
||||
.replace(mathjaxInlineDelimiterPattern, (_match: string, text: string) => {
|
||||
const escaped = translateEntitiesToMathjax(text);
|
||||
return `<${Mathjax.tagName}>${escaped}</${Mathjax.tagName}>`;
|
||||
return `<${Mathjax.tagName}>${text}</${Mathjax.tagName}>`;
|
||||
});
|
||||
}
|
||||
|
||||
@ -107,7 +97,7 @@ export const Mathjax: DecoratedElementConstructor = class Mathjax
|
||||
return;
|
||||
}
|
||||
|
||||
this.dataset.mathjax = this.innerText;
|
||||
this.dataset.mathjax = this.innerHTML;
|
||||
this.innerHTML = "";
|
||||
this.style.whiteSpace = "normal";
|
||||
|
||||
|
@ -65,3 +65,14 @@ export function convertMathjax(
|
||||
|
||||
return [svg.outerHTML, title];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, ">");
|
||||
}
|
||||
|
@ -87,13 +87,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Escape characters which are technically legal in Mathjax, but confuse HTML.
|
||||
*/
|
||||
export function escapeSomeEntities(value: string): string {
|
||||
return value.replace(/</g, "{\\lt}").replace(/>/g, "{\\gt}");
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mathjax-editor">
|
||||
@ -101,7 +94,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
{code}
|
||||
{configuration}
|
||||
bind:api={codeMirror}
|
||||
on:change={({ detail }) => code.set(escapeSomeEntities(detail))}
|
||||
on:change={({ detail: mathjaxText }) => code.set(mathjaxText)}
|
||||
on:blur
|
||||
/>
|
||||
</div>
|
||||
|
@ -8,6 +8,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
import WithDropdown from "../../components/WithDropdown.svelte";
|
||||
import { escapeSomeEntities, unescapeSomeEntities } from "../../editable/mathjax";
|
||||
import { Mathjax } from "../../editable/mathjax-element";
|
||||
import { on } from "../../lib/events";
|
||||
import { noop } from "../../lib/functional";
|
||||
@ -20,8 +21,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
const { container, api } = context.get();
|
||||
const { editable, preventResubscription } = api;
|
||||
|
||||
const code = writable("");
|
||||
|
||||
let activeImage: HTMLImageElement | null = null;
|
||||
let mathjaxElement: HTMLElement | null = null;
|
||||
let allow = noop;
|
||||
@ -30,6 +29,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
let selectAll = false;
|
||||
let position: CodeMirrorLib.Position | undefined = undefined;
|
||||
|
||||
/**
|
||||
* Will contain the Mathjax text with unescaped entities.
|
||||
* This is the text displayed in the actual editor window.
|
||||
*/
|
||||
const code = writable("");
|
||||
|
||||
function showHandle(image: HTMLImageElement, pos?: CodeMirrorLib.Position): void {
|
||||
allow = preventResubscription();
|
||||
position = pos;
|
||||
@ -39,9 +44,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
activeImage = image;
|
||||
mathjaxElement = activeImage.closest(Mathjax.tagName)!;
|
||||
|
||||
code.set(mathjaxElement.dataset.mathjax ?? "");
|
||||
code.set(unescapeSomeEntities(mathjaxElement.dataset.mathjax ?? ""));
|
||||
unsubscribe = code.subscribe((value: string) => {
|
||||
mathjaxElement!.dataset.mathjax = value;
|
||||
mathjaxElement!.dataset.mathjax = escapeSomeEntities(value);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -23,11 +23,11 @@ function adjustInputFragment(fragment: DocumentFragment): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function storedToFragment(html: string): DocumentFragment {
|
||||
export function storedToFragment(storedHTML: string): DocumentFragment {
|
||||
/* We need .createContextualFragment so that customElements are initialized */
|
||||
const fragment = document
|
||||
.createRange()
|
||||
.createContextualFragment(createDummyDoc(adjustInputHTML(html)));
|
||||
.createContextualFragment(createDummyDoc(adjustInputHTML(storedHTML)));
|
||||
|
||||
adjustInputFragment(fragment);
|
||||
return fragment;
|
||||
@ -56,5 +56,6 @@ export function fragmentToStored(fragment: DocumentFragment): string {
|
||||
const clone = document.importNode(fragment, true);
|
||||
adjustOutputFragment(clone);
|
||||
|
||||
return adjustOutputHTML(fragmentToString(clone));
|
||||
const storedHTML = adjustOutputHTML(fragmentToString(clone));
|
||||
return storedHTML;
|
||||
}
|
||||
|
@ -110,6 +110,9 @@ export function nodeContainsInlineContent(node: Node): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes the input fragment.
|
||||
*/
|
||||
export function fragmentToString(fragment: DocumentFragment): string {
|
||||
const fragmentDiv = document.createElement("div");
|
||||
fragmentDiv.appendChild(fragment);
|
||||
|
Loading…
Reference in New Issue
Block a user