Make text wrapper buttons work with Codable

This commit is contained in:
Henrik Giesel 2021-06-18 02:33:56 +02:00
parent 8a07d3161d
commit a3a59f0293
6 changed files with 34 additions and 15 deletions

View file

@ -12,14 +12,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { bracketsIcon } from "./icons"; import { bracketsIcon } from "./icons";
import { forEditorField } from "."; import { forEditorField } from ".";
import { wrap } from "./wrap"; import { wrapCurrent } from "./wrap";
const clozePattern = /\{\{c(\d+)::/gu; const clozePattern = /\{\{c(\d+)::/gu;
function getCurrentHighestCloze(increment: boolean): number { function getCurrentHighestCloze(increment: boolean): number {
let highest = 0; let highest = 0;
forEditorField([], (field) => { forEditorField([], (field) => {
const fieldHTML = field.editingArea.editable.fieldHTML; const fieldHTML = field.editingArea.fieldHTML;
const matches: number[] = []; const matches: number[] = [];
let match: RegExpMatchArray | null = null; 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 { function onCloze(event: KeyboardEvent | MouseEvent): void {
const highestCloze = getCurrentHighestCloze(!event.getModifierState("Alt")); const highestCloze = getCurrentHighestCloze(!event.getModifierState("Alt"));
wrap(`{{c${highestCloze}::`, "}}"); wrapCurrent(`{{c${highestCloze}::`, "}}");
} }
</script> </script>

View file

@ -19,9 +19,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import OnlyEditable from "./OnlyEditable.svelte"; import OnlyEditable from "./OnlyEditable.svelte";
import ClozeButton from "./ClozeButton.svelte"; import ClozeButton from "./ClozeButton.svelte";
import { wrap } from "./wrap";
import { appendInParentheses } from "./helpers";
import { getCurrentField } from "."; import { getCurrentField } from ".";
import { appendInParentheses } from "./helpers";
import { wrapCurrent } from "./wrap";
import { paperclipIcon, micIcon, functionIcon, xmlIcon } from "./icons"; import { paperclipIcon, micIcon, functionIcon, xmlIcon } from "./icons";
export let api = {}; export let api = {};
@ -98,7 +98,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let:shortcutLabel let:shortcutLabel
> >
<DropdownItem <DropdownItem
on:click={() => wrap("\\(", "\\)")} on:click={() => wrapCurrent("\\(", "\\)")}
on:mount={createShortcut} on:mount={createShortcut}
> >
{tr.editingMathjaxInline()} {tr.editingMathjaxInline()}
@ -112,7 +112,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let:shortcutLabel let:shortcutLabel
> >
<DropdownItem <DropdownItem
on:click={() => wrap("\\[", "\\]")} on:click={() => wrapCurrent("\\[", "\\]")}
on:mount={createShortcut} on:mount={createShortcut}
> >
{tr.editingMathjaxBlock()} {tr.editingMathjaxBlock()}
@ -126,7 +126,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let:shortcutLabel let:shortcutLabel
> >
<DropdownItem <DropdownItem
on:click={() => wrap("\\(\\ce{", "}\\)")} on:click={() => wrapCurrent("\\(\\ce{", "}\\)")}
on:mount={createShortcut} on:mount={createShortcut}
> >
{tr.editingMathjaxChemistry()} {tr.editingMathjaxChemistry()}
@ -140,7 +140,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let:shortcutLabel let:shortcutLabel
> >
<DropdownItem <DropdownItem
on:click={() => wrap("[latex]", "[/latex]")} on:click={() => wrapCurrent("[latex]", "[/latex]")}
on:mount={createShortcut} on:mount={createShortcut}
> >
{tr.editingLatex()} {tr.editingLatex()}
@ -154,7 +154,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let:shortcutLabel let:shortcutLabel
> >
<DropdownItem <DropdownItem
on:click={() => wrap("[$]", "[/$]")} on:click={() => wrapCurrent("[$]", "[/$]")}
on:mount={createShortcut} on:mount={createShortcut}
> >
{tr.editingLatexEquation()} {tr.editingLatexEquation()}
@ -168,7 +168,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let:shortcutLabel let:shortcutLabel
> >
<DropdownItem <DropdownItem
on:click={() => wrap("[$$]", "[/$$]")} on:click={(event) => wrapCurrent("[$$]", "[/$$]", event)}
on:mount={createShortcut} on:mount={createShortcut}
> >
{tr.editingLatexMathEnv()} {tr.editingLatexMathEnv()}

View file

@ -74,6 +74,11 @@ export class Codable extends HTMLTextAreaElement {
this.codeMirror.setCursor(this.codeMirror.lineCount(), 0); 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 { onEnter(): void {
/* default */ /* default */
} }

View file

@ -4,6 +4,7 @@
import { bridgeCommand } from "./lib"; import { bridgeCommand } from "./lib";
import { nodeIsInline, caretToEnd, getBlockElement } from "./helpers"; import { nodeIsInline, caretToEnd, getBlockElement } from "./helpers";
import { setEditableButtons } from "./toolbar"; import { setEditableButtons } from "./toolbar";
import { wrap } from "./wrap";
function containsInlineContent(field: Element): boolean { function containsInlineContent(field: Element): boolean {
if (field.childNodes.length === 0) { if (field.childNodes.length === 0) {
@ -48,6 +49,10 @@ export class Editable extends HTMLElement {
caretToEnd(this); caretToEnd(this);
} }
surroundSelection(before: string, after: string): void {
wrap(before, after);
}
onEnter(event: KeyboardEvent): void { onEnter(event: KeyboardEvent): void {
if ( if (
!getBlockElement(this.getRootNode() as Document | ShadowRoot) !== !getBlockElement(this.getRootNode() as Document | ShadowRoot) !==

View file

@ -115,10 +115,6 @@ export class EditingArea extends HTMLDivElement {
return firstRule.style.direction === "rtl"; return firstRule.style.direction === "rtl";
} }
getSelection(): Selection {
return this.shadowRoot!.getSelection()!;
}
focus(): void { focus(): void {
this.activeInput.focus(); this.activeInput.focus();
} }
@ -135,6 +131,14 @@ export class EditingArea extends HTMLDivElement {
return document.activeElement === this; 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 { onEnter(event: KeyboardEvent): void {
this.activeInput.onEnter(event); this.activeInput.onEnter(event);
} }

View file

@ -45,6 +45,11 @@ export function wrap(front: string, back: string): void {
wrapInternal(front, back, false); wrapInternal(front, back, false);
} }
export function wrapCurrent(front: string, back: string): void {
const currentField = getCurrentField()!;
currentField.surroundSelection(front, back);
}
/* currently unused */ /* currently unused */
export function wrapIntoText(front: string, back: string): void { export function wrapIntoText(front: string, back: string): void {
wrapInternal(front, back, true); wrapInternal(front, back, true);