From 50e36bc312b64c59fcd53c283596daeeaba9521e Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Fri, 25 Feb 2022 02:14:26 +0100 Subject: [PATCH] Fix plain text (#1689) * Move remove-prohibited-tags logic from PlainTextInput * Make CodeMirror export a promise * Offer lifecycle hooks for PlainTextInput for easily accessing code mirror instance * Fix breaking Mathjax * remove debug statement (dae) --- ts/editable/decorated.ts | 32 ++++- ts/editable/mathjax-element.ts | 33 ++++-- ts/editor/CodeMirror.svelte | 110 ++++++++---------- ts/editor/DecoratedElements.svelte | 10 +- ts/editor/NoteEditor.svelte | 2 +- ts/editor/code-mirror.ts | 79 ++++++++++++- .../mathjax-overlay/MathjaxEditor.svelte | 87 ++++++++------ .../mathjax-overlay/MathjaxHandle.svelte | 8 +- .../plain-text-input/PlainTextInput.svelte | 96 ++++++--------- .../plain-text-input/remove-prohibited.ts | 38 ++++++ ts/lib/runtime-require.ts | 1 + ts/sveltelib/lifecycle-hooks.ts | 3 +- 12 files changed, 307 insertions(+), 192 deletions(-) create mode 100644 ts/editor/plain-text-input/remove-prohibited.ts diff --git a/ts/editable/decorated.ts b/ts/editable/decorated.ts index 760e75208..8df02479e 100644 --- a/ts/editable/decorated.ts +++ b/ts/editable/decorated.ts @@ -38,13 +38,37 @@ export interface DecoratedElementConstructor toUndecorated(stored: string): string; } -export class CustomElementArray< - T extends CustomElementConstructor & WithTagName, -> extends Array { - push(...elements: T[]): number { +export class CustomElementArray extends Array { + push(...elements: DecoratedElementConstructor[]): number { for (const element of elements) { customElements.define(element.tagName, element); } return super.push(...elements); } + + /** + * Transforms any decorated elements in input HTML from undecorated to stored state. + */ + toStored(html: string): string { + let result = html; + + for (const element of this) { + result = element.toStored(result); + } + + return result; + } + + /** + * Transforms any decorated elements in input HTML from stored to undecorated state. + */ + toUndecorated(html: string): string { + let result = html; + + for (const element of this) { + result = element.toUndecorated(result); + } + + return result; + } } diff --git a/ts/editable/mathjax-element.ts b/ts/editable/mathjax-element.ts index 73610c34f..1cfbcfdba 100644 --- a/ts/editable/mathjax-element.ts +++ b/ts/editable/mathjax-element.ts @@ -15,6 +15,14 @@ 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 @@ -22,7 +30,7 @@ export const Mathjax: DecoratedElementConstructor = class Mathjax static tagName = "anki-mathjax"; static toStored(undecorated: string): string { - return undecorated.replace( + const stored = undecorated.replace( mathjaxTagPattern, (_match: string, block: string | undefined, text: string) => { return typeof block === "string" && block !== "false" @@ -30,20 +38,20 @@ export const Mathjax: DecoratedElementConstructor = class Mathjax : `\\(${text}\\)`; }, ); + + return stored; } static toUndecorated(stored: string): string { return stored - .replace( - mathjaxBlockDelimiterPattern, - (_match: string, text: string) => - `<${Mathjax.tagName} block="true">${text}`, - ) - .replace( - mathjaxInlineDelimiterPattern, - (_match: string, text: string) => - `<${Mathjax.tagName}>${text}`, - ); + .replace(mathjaxBlockDelimiterPattern, (_match: string, text: string) => { + const escaped = translateEntitiesToMathjax(text); + return `<${Mathjax.tagName} block="true">${escaped}`; + }) + .replace(mathjaxInlineDelimiterPattern, (_match: string, text: string) => { + const escaped = translateEntitiesToMathjax(text); + return `<${Mathjax.tagName}>${escaped}`; + }); } block = false; @@ -76,6 +84,9 @@ export const Mathjax: DecoratedElementConstructor = class Mathjax break; case "data-mathjax": + if (!newValue) { + return; + } this.component?.$set({ mathjax: newValue }); break; } diff --git a/ts/editor/CodeMirror.svelte b/ts/editor/CodeMirror.svelte index 3b2ab8136..755365544 100644 --- a/ts/editor/CodeMirror.svelte +++ b/ts/editor/CodeMirror.svelte @@ -3,92 +3,84 @@ Copyright: Ankitects Pty Ltd and contributors License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -->
-