From a3a59f0293478b6815de45338437b35d7c3457a6 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Fri, 18 Jun 2021 02:33:56 +0200 Subject: [PATCH] Make text wrapper buttons work with Codable --- ts/editor/ClozeButton.svelte | 6 +++--- ts/editor/TemplateButtons.svelte | 16 ++++++++-------- ts/editor/codable.ts | 5 +++++ ts/editor/editable.ts | 5 +++++ ts/editor/editingArea.ts | 12 ++++++++---- ts/editor/wrap.ts | 5 +++++ 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/ts/editor/ClozeButton.svelte b/ts/editor/ClozeButton.svelte index b2c444257..a6e5da7d5 100644 --- a/ts/editor/ClozeButton.svelte +++ b/ts/editor/ClozeButton.svelte @@ -12,14 +12,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import { bracketsIcon } from "./icons"; import { forEditorField } from "."; - import { wrap } from "./wrap"; + import { wrapCurrent } from "./wrap"; const clozePattern = /\{\{c(\d+)::/gu; function getCurrentHighestCloze(increment: boolean): number { let highest = 0; forEditorField([], (field) => { - const fieldHTML = field.editingArea.editable.fieldHTML; + const fieldHTML = field.editingArea.fieldHTML; const matches: number[] = []; let match: RegExpMatchArray | null = null; @@ -39,7 +39,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html function onCloze(event: KeyboardEvent | MouseEvent): void { const highestCloze = getCurrentHighestCloze(!event.getModifierState("Alt")); - wrap(`{{c${highestCloze}::`, "}}"); + wrapCurrent(`{{c${highestCloze}::`, "}}"); } diff --git a/ts/editor/TemplateButtons.svelte b/ts/editor/TemplateButtons.svelte index 79cd7f398..5ffe9f8ba 100644 --- a/ts/editor/TemplateButtons.svelte +++ b/ts/editor/TemplateButtons.svelte @@ -19,9 +19,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import OnlyEditable from "./OnlyEditable.svelte"; import ClozeButton from "./ClozeButton.svelte"; - import { wrap } from "./wrap"; - import { appendInParentheses } from "./helpers"; import { getCurrentField } from "."; + import { appendInParentheses } from "./helpers"; + import { wrapCurrent } from "./wrap"; import { paperclipIcon, micIcon, functionIcon, xmlIcon } from "./icons"; export let api = {}; @@ -98,7 +98,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html let:shortcutLabel > wrap("\\(", "\\)")} + on:click={() => wrapCurrent("\\(", "\\)")} on:mount={createShortcut} > {tr.editingMathjaxInline()} @@ -112,7 +112,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html let:shortcutLabel > wrap("\\[", "\\]")} + on:click={() => wrapCurrent("\\[", "\\]")} on:mount={createShortcut} > {tr.editingMathjaxBlock()} @@ -126,7 +126,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html let:shortcutLabel > wrap("\\(\\ce{", "}\\)")} + on:click={() => wrapCurrent("\\(\\ce{", "}\\)")} on:mount={createShortcut} > {tr.editingMathjaxChemistry()} @@ -140,7 +140,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html let:shortcutLabel > wrap("[latex]", "[/latex]")} + on:click={() => wrapCurrent("[latex]", "[/latex]")} on:mount={createShortcut} > {tr.editingLatex()} @@ -154,7 +154,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html let:shortcutLabel > wrap("[$]", "[/$]")} + on:click={() => wrapCurrent("[$]", "[/$]")} on:mount={createShortcut} > {tr.editingLatexEquation()} @@ -168,7 +168,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html let:shortcutLabel > wrap("[$$]", "[/$$]")} + on:click={(event) => wrapCurrent("[$$]", "[/$$]", event)} on:mount={createShortcut} > {tr.editingLatexMathEnv()} diff --git a/ts/editor/codable.ts b/ts/editor/codable.ts index f243085be..568ef6aaf 100644 --- a/ts/editor/codable.ts +++ b/ts/editor/codable.ts @@ -74,6 +74,11 @@ export class Codable extends HTMLTextAreaElement { this.codeMirror.setCursor(this.codeMirror.lineCount(), 0); } + surroundSelection(before: string, after: string): void { + const selection = this.codeMirror.getSelection(); + this.codeMirror.replaceSelection(before + selection + after); + } + onEnter(): void { /* default */ } diff --git a/ts/editor/editable.ts b/ts/editor/editable.ts index 78a2e9dd9..c537cb189 100644 --- a/ts/editor/editable.ts +++ b/ts/editor/editable.ts @@ -4,6 +4,7 @@ import { bridgeCommand } from "./lib"; import { nodeIsInline, caretToEnd, getBlockElement } from "./helpers"; import { setEditableButtons } from "./toolbar"; +import { wrap } from "./wrap"; function containsInlineContent(field: Element): boolean { if (field.childNodes.length === 0) { @@ -48,6 +49,10 @@ export class Editable extends HTMLElement { caretToEnd(this); } + surroundSelection(before: string, after: string): void { + wrap(before, after); + } + onEnter(event: KeyboardEvent): void { if ( !getBlockElement(this.getRootNode() as Document | ShadowRoot) !== diff --git a/ts/editor/editingArea.ts b/ts/editor/editingArea.ts index efe211764..a1d9f8f11 100644 --- a/ts/editor/editingArea.ts +++ b/ts/editor/editingArea.ts @@ -115,10 +115,6 @@ export class EditingArea extends HTMLDivElement { return firstRule.style.direction === "rtl"; } - getSelection(): Selection { - return this.shadowRoot!.getSelection()!; - } - focus(): void { this.activeInput.focus(); } @@ -135,6 +131,14 @@ export class EditingArea extends HTMLDivElement { return document.activeElement === this; } + getSelection(): Selection { + return this.shadowRoot!.getSelection()!; + } + + surroundSelection(before: string, after: string): void { + this.activeInput.surroundSelection(before, after); + } + onEnter(event: KeyboardEvent): void { this.activeInput.onEnter(event); } diff --git a/ts/editor/wrap.ts b/ts/editor/wrap.ts index 4255d4d80..8b67d776b 100644 --- a/ts/editor/wrap.ts +++ b/ts/editor/wrap.ts @@ -45,6 +45,11 @@ export function wrap(front: string, back: string): void { wrapInternal(front, back, false); } +export function wrapCurrent(front: string, back: string): void { + const currentField = getCurrentField()!; + currentField.surroundSelection(front, back); +} + /* currently unused */ export function wrapIntoText(front: string, back: string): void { wrapInternal(front, back, true);