@@ -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
/>
diff --git a/ts/editor/mathjax-overlay/MathjaxHandle.svelte b/ts/editor/mathjax-overlay/MathjaxHandle.svelte
index 6f13d384d..4b58ef1f3 100644
--- a/ts/editor/mathjax-overlay/MathjaxHandle.svelte
+++ b/ts/editor/mathjax-overlay/MathjaxHandle.svelte
@@ -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);
});
}
diff --git a/ts/editor/rich-text-input/transform.ts b/ts/editor/rich-text-input/transform.ts
index 185992834..33ce0afb8 100644
--- a/ts/editor/rich-text-input/transform.ts
+++ b/ts/editor/rich-text-input/transform.ts
@@ -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;
}
diff --git a/ts/editor/tag-editor/WithAutocomplete.svelte b/ts/editor/tag-editor/WithAutocomplete.svelte
index 54112883d..9ffbacc3e 100644
--- a/ts/editor/tag-editor/WithAutocomplete.svelte
+++ b/ts/editor/tag-editor/WithAutocomplete.svelte
@@ -8,6 +8,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import Popover from "../../components/Popover.svelte";
import WithFloating from "../../components/WithFloating.svelte";
+ import { isApplePlatform } from "../../lib/platform";
import AutocompleteItem from "./AutocompleteItem.svelte";
export let suggestionsPromise: Promise;
@@ -16,6 +17,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let suggestionsItems: string[] = [];
$: suggestionsPromise.then((items) => {
show.set(items.length > 0);
+ if (isApplePlatform() && navigator.userAgent.match(/Chrome\/77/)) {
+ items = items.slice(0, 10);
+ }
suggestionsItems = items;
});
diff --git a/ts/graphs/future-due.ts b/ts/graphs/future-due.ts
index 801ac94e7..89801b9f7 100644
--- a/ts/graphs/future-due.ts
+++ b/ts/graphs/future-due.ts
@@ -16,7 +16,7 @@ import {
sum,
} from "d3";
-import { CardQueue } from "../lib/cards";
+import { CardType } from "../lib/cards";
import * as tr from "../lib/ftl";
import { localizedNumber } from "../lib/i18n";
import type { Cards, Stats } from "../lib/proto";
@@ -31,19 +31,15 @@ export interface GraphData {
}
export function gatherData(data: Stats.GraphsResponse): GraphData {
- const isLearning = (card: Cards.Card): boolean =>
- [CardQueue.Learn, CardQueue.PreviewRepeat].includes(card.queue);
-
+ const isIntradayLearning = (card: Cards.Card, due: number): boolean => {
+ return (
+ [CardType.Learn, CardType.Relearn].includes(card.ctype) &&
+ due > 1_000_000_000
+ );
+ };
let haveBacklog = false;
const due = (data.cards as Cards.Card[])
- .filter((c: Cards.Card) => {
- // reviews
- return (
- [CardQueue.Review, CardQueue.DayLearn].includes(c.queue) ||
- // or learning cards
- isLearning(c)
- );
- })
+ .filter((c: Cards.Card) => c.queue >= 0)
.map((c: Cards.Card) => {
// - testing just odue fails on day 1
// - testing just odid fails on lapsed cards that
@@ -51,7 +47,7 @@ export function gatherData(data: Stats.GraphsResponse): GraphData {
const due = c.originalDeckId && c.originalDue ? c.originalDue : c.due;
let dueDay: number;
- if (isLearning(c)) {
+ if (isIntradayLearning(c, due)) {
const offset = due - data.nextDayAtSecs;
dueDay = Math.floor(offset / 86_400) + 1;
} else {
diff --git a/ts/lib/dom.ts b/ts/lib/dom.ts
index 1cf599050..60b79689a 100644
--- a/ts/lib/dom.ts
+++ b/ts/lib/dom.ts
@@ -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);
diff --git a/ts/sveltelib/input-handler.ts b/ts/sveltelib/input-handler.ts
index ff0ec573b..8bd0bc2c4 100644
--- a/ts/sveltelib/input-handler.ts
+++ b/ts/sveltelib/input-handler.ts
@@ -61,21 +61,8 @@ function useInputHandler(): [InputHandlerAPI, SetupInputHandlerAction] {
insertText.clear();
}
- function onInput(this: HTMLElement, event: InputEvent): void {
- // prevent unwanted from being left behind when clearing field contents
- if (
- !event.data &&
- this.children.length === 1 &&
- this.children.item(0) instanceof HTMLDivElement &&
- /^\n?$/.test(this.innerText)
- ) {
- this.innerHTML = "";
- }
- }
-
function setupHandler(element: HTMLElement): { destroy(): void } {
const beforeInputOff = on(element, "beforeinput", onBeforeInput);
- const inputOff = on(element, "input" as "beforeinput", onInput);
const blurOff = on(element, "blur", clearInsertText);
const pointerDownOff = on(element, "pointerdown", clearInsertText);
@@ -84,7 +71,6 @@ function useInputHandler(): [InputHandlerAPI, SetupInputHandlerAction] {
return {
destroy() {
beforeInputOff();
- inputOff();
blurOff();
pointerDownOff();
selectionChangeOff();