mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
Set caret inside chemical expression in Mathjax (#1763)
This commit is contained in:
parent
6718e67883
commit
67c1f7368e
7 changed files with 86 additions and 51 deletions
|
@ -41,11 +41,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
let image: HTMLImageElement;
|
let image: HTMLImageElement;
|
||||||
|
|
||||||
export function moveCaretAfter(): void {
|
export function moveCaretAfter(position?: [number, number]): void {
|
||||||
// This should trigger a focusing of the Mathjax Handle
|
// This should trigger a focusing of the Mathjax Handle
|
||||||
image.dispatchEvent(
|
image.dispatchEvent(
|
||||||
new CustomEvent("movecaretafter", {
|
new CustomEvent("movecaretafter", {
|
||||||
detail: image,
|
detail: { image, position },
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
composed: true,
|
composed: true,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -121,7 +121,15 @@ export const Mathjax: DecoratedElementConstructor = class Mathjax
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.hasAttribute("focusonmount")) {
|
if (this.hasAttribute("focusonmount")) {
|
||||||
this.component.moveCaretAfter();
|
let position: [number, number] | undefined = undefined;
|
||||||
|
|
||||||
|
if (this.getAttribute("focusonmount")!.length > 0) {
|
||||||
|
position = this.getAttribute("focusonmount")!
|
||||||
|
.split(",")
|
||||||
|
.map(Number) as [number, number];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.component.moveCaretAfter(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setAttribute("contentEditable", "false");
|
this.setAttribute("contentEditable", "false");
|
||||||
|
|
|
@ -52,9 +52,12 @@ export const gutterOptions: CodeMirror.EditorConfiguration = {
|
||||||
foldGutter: true,
|
foldGutter: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function focusAndCaretAfter(editor: CodeMirror.Editor): void {
|
export function focusAndSetCaret(
|
||||||
|
editor: CodeMirror.Editor,
|
||||||
|
position: CodeMirror.Position = { line: editor.lineCount(), ch: 0 },
|
||||||
|
): void {
|
||||||
editor.focus();
|
editor.focus();
|
||||||
editor.setCursor(editor.lineCount(), 0);
|
editor.setCursor(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OpenCodeMirrorOptions {
|
interface OpenCodeMirrorOptions {
|
||||||
|
|
|
@ -35,7 +35,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMathjaxChemistry(): void {
|
function onMathjaxChemistry(): void {
|
||||||
surround("<anki-mathjax focusonmount>\\ce{", "}</anki-mathjax>");
|
surround('<anki-mathjax focusonmount="0,4">\\ce{', "}</anki-mathjax>");
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLatex(): void {
|
function onLatex(): void {
|
||||||
|
|
|
@ -10,7 +10,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import * as tr from "../../lib/ftl";
|
import * as tr from "../../lib/ftl";
|
||||||
import { noop } from "../../lib/functional";
|
import { noop } from "../../lib/functional";
|
||||||
import { getPlatformString } from "../../lib/shortcuts";
|
import { getPlatformString } from "../../lib/shortcuts";
|
||||||
import { baseOptions, focusAndCaretAfter, latex } from "../code-mirror";
|
import { baseOptions, focusAndSetCaret, latex } from "../code-mirror";
|
||||||
import type { CodeMirrorAPI } from "../CodeMirror.svelte";
|
import type { CodeMirrorAPI } from "../CodeMirror.svelte";
|
||||||
import CodeMirror from "../CodeMirror.svelte";
|
import CodeMirror from "../CodeMirror.svelte";
|
||||||
|
|
||||||
|
@ -33,15 +33,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
mode: latex,
|
mode: latex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* These are not reactive, but only operate on initialization */
|
||||||
|
export let position: CodeMirrorLib.Position | undefined = undefined;
|
||||||
export let selectAll: boolean;
|
export let selectAll: boolean;
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
let codeMirror = {} as CodeMirrorAPI;
|
let codeMirror = {} as CodeMirrorAPI;
|
||||||
|
|
||||||
onMount(() =>
|
onMount(async () => {
|
||||||
codeMirror.editor.then((editor) => {
|
const editor = await codeMirror.editor;
|
||||||
focusAndCaretAfter(editor);
|
|
||||||
|
focusAndSetCaret(editor, position);
|
||||||
|
|
||||||
if (selectAll) {
|
if (selectAll) {
|
||||||
editor.execCommand("selectAll");
|
editor.execCommand("selectAll");
|
||||||
|
@ -83,8 +86,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
direction = undefined;
|
direction = undefined;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}),
|
});
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escape characters which are technically legal in Mathjax, but confuse HTML.
|
* Escape characters which are technically legal in Mathjax, but confuse HTML.
|
||||||
|
|
|
@ -3,6 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type CodeMirrorLib from "codemirror";
|
||||||
import { onDestroy, onMount, tick } from "svelte";
|
import { onDestroy, onMount, tick } from "svelte";
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
@ -26,9 +27,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
let allow = noop;
|
let allow = noop;
|
||||||
let unsubscribe = noop;
|
let unsubscribe = noop;
|
||||||
|
|
||||||
function showHandle(image: HTMLImageElement): void {
|
let selectAll = false;
|
||||||
allow = preventResubscription();
|
let position: CodeMirrorLib.Position | undefined = undefined;
|
||||||
|
|
||||||
|
function showHandle(image: HTMLImageElement, pos?: CodeMirrorLib.Position): void {
|
||||||
|
allow = preventResubscription();
|
||||||
|
position = pos;
|
||||||
|
|
||||||
|
/* Setting the activeImage and mathjaxElement to a non-nullish value is
|
||||||
|
* what triggers the Mathjax editor to show */
|
||||||
activeImage = image;
|
activeImage = image;
|
||||||
mathjaxElement = activeImage.closest(Mathjax.tagName)!;
|
mathjaxElement = activeImage.closest(Mathjax.tagName)!;
|
||||||
|
|
||||||
|
@ -38,8 +45,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectAll = false;
|
|
||||||
|
|
||||||
function placeHandle(after: boolean): void {
|
function placeHandle(after: boolean): void {
|
||||||
editable.focusHandler.flushCaret();
|
editable.focusHandler.flushCaret();
|
||||||
|
|
||||||
|
@ -52,6 +57,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
async function resetHandle(): Promise<void> {
|
async function resetHandle(): Promise<void> {
|
||||||
selectAll = false;
|
selectAll = false;
|
||||||
|
position = undefined;
|
||||||
|
|
||||||
if (activeImage && mathjaxElement) {
|
if (activeImage && mathjaxElement) {
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
|
@ -72,9 +78,20 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
async function showAutofocusHandle({
|
async function showAutofocusHandle({
|
||||||
detail,
|
detail,
|
||||||
}: CustomEvent<HTMLImageElement>): Promise<void> {
|
}: CustomEvent<{
|
||||||
|
image: HTMLImageElement;
|
||||||
|
position?: [number, number];
|
||||||
|
}>): Promise<void> {
|
||||||
|
let position: CodeMirrorLib.Position | undefined = undefined;
|
||||||
|
|
||||||
await resetHandle();
|
await resetHandle();
|
||||||
showHandle(detail);
|
|
||||||
|
if (detail.position) {
|
||||||
|
const [line, ch] = detail.position;
|
||||||
|
position = { line, ch };
|
||||||
|
}
|
||||||
|
|
||||||
|
showHandle(detail.image, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showSelectAll({
|
async function showSelectAll({
|
||||||
|
@ -138,6 +155,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
element={mathjaxElement}
|
element={mathjaxElement}
|
||||||
{code}
|
{code}
|
||||||
{selectAll}
|
{selectAll}
|
||||||
|
{position}
|
||||||
bind:updateSelection
|
bind:updateSelection
|
||||||
on:reset={resetHandle}
|
on:reset={resetHandle}
|
||||||
on:moveoutstart={() => {
|
on:moveoutstart={() => {
|
||||||
|
|
|
@ -3,6 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type CodeMirrorLib from "codemirror";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
import type { Writable } from "svelte/store";
|
import type { Writable } from "svelte/store";
|
||||||
|
|
||||||
|
@ -15,7 +16,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
export let element: Element;
|
export let element: Element;
|
||||||
export let code: Writable<string>;
|
export let code: Writable<string>;
|
||||||
|
|
||||||
export let selectAll: boolean;
|
export let selectAll: boolean;
|
||||||
|
export let position: CodeMirrorLib.Position | undefined;
|
||||||
|
|
||||||
const acceptShortcut = "Enter";
|
const acceptShortcut = "Enter";
|
||||||
const newlineShortcut = "Shift+Enter";
|
const newlineShortcut = "Shift+Enter";
|
||||||
|
@ -40,6 +43,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
{newlineShortcut}
|
{newlineShortcut}
|
||||||
{code}
|
{code}
|
||||||
{selectAll}
|
{selectAll}
|
||||||
|
{position}
|
||||||
on:blur={() => dispatch("reset")}
|
on:blur={() => dispatch("reset")}
|
||||||
on:moveoutstart
|
on:moveoutstart
|
||||||
on:moveoutend
|
on:moveoutend
|
||||||
|
|
Loading…
Reference in a new issue