Fix some cloze handling regressions (#3086)

* Place cursor inside empty clozes

* Remove empty <li> after being added
This commit is contained in:
Abdo 2024-03-31 12:01:17 +03:00 committed by GitHub
parent 9c733848b8
commit 31e2dc1409
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,7 +3,6 @@
import { placeCaretAfter } from "../domlib/place-caret"; import { placeCaretAfter } from "../domlib/place-caret";
import { getRange, getSelection } from "./cross-browser"; import { getRange, getSelection } from "./cross-browser";
import { nodeIsElement } from "./dom";
function wrappedExceptForWhitespace(text: string, front: string, back: string): string { function wrappedExceptForWhitespace(text: string, front: string, back: string): string {
const match = text.match(/^(\s*)([^]*?)(\s*)$/)!; const match = text.match(/^(\s*)([^]*?)(\s*)$/)!;
@ -63,56 +62,10 @@ export function wrapClozeInternal(base: Element, n: number): void {
return; return;
} }
// Expand the range to include parent nodes whose children are already included.
// This is to work around .extractContents() adding redundant empty elements
let startParent: Node | null = range.startContainer.parentNode;
if (
startParent !== base
&& startParent?.firstChild === range.startContainer && range.startOffset === 0
) {
range.setStartBefore(startParent);
}
let endParent: Node | null = range.endContainer.parentNode;
if (
endParent !== base
&& endParent?.lastChild === range.endContainer && (
(!nodeIsElement(range.endContainer)
&& range.endOffset === range.endContainer.textContent?.length)
|| (nodeIsElement(range.endContainer)
&& range.endOffset === range.endContainer.childNodes.length)
)
) {
range.setEndAfter(endParent);
}
let expand: boolean;
do {
expand = false;
if (
startParent
&& startParent.parentNode !== base && startParent.parentNode?.firstChild === startParent
&& range.isPointInRange(startParent.parentNode, startParent.parentNode?.childNodes.length)
) {
startParent = startParent.parentNode;
range.setStartBefore(startParent);
expand = true;
}
if (
endParent && endParent.parentNode !== base && endParent.parentNode?.lastChild === endParent
&& range.isPointInRange(endParent.parentNode, 0)
) {
endParent = endParent.parentNode;
range.setEndAfter(endParent);
expand = true;
}
if (range.endOffset === 0) {
range.setEndBefore(range.endContainer);
expand = true;
}
} while (expand);
const fragment = range.extractContents(); const fragment = range.extractContents();
if (fragment.childNodes.length === 0) { if (fragment.childNodes.length === 0) {
document.execCommand("inserthtml", false, `{{c${n}::}}`); document.execCommand("inserthtml", false, `{{c${n}::}}`);
moveCursorInside(selection, "}}");
} else { } else {
const startNode = document.createTextNode(`{{c${n}::`); const startNode = document.createTextNode(`{{c${n}::`);
const endNode = document.createTextNode("}}"); const endNode = document.createTextNode("}}");
@ -120,5 +73,17 @@ export function wrapClozeInternal(base: Element, n: number): void {
range.insertNode(fragment); range.insertNode(fragment);
range.insertNode(startNode); range.insertNode(startNode);
placeCaretAfter(endNode); placeCaretAfter(endNode);
// Remove empty <li> elements added by extractContents()
const elementsToCheck = [
startNode.previousElementSibling,
startNode.nextElementSibling,
endNode.previousElementSibling,
endNode.nextElementSibling,
];
for (const element of elementsToCheck) {
if (element?.tagName === "LI" && !element?.textContent?.trim()) {
element.remove();
}
}
} }
} }