Improve Squire with isBrElement()

This commit is contained in:
the-djmaze 2023-12-26 00:58:43 +01:00
parent 98b203a3ca
commit 508f5cc6e5

View file

@ -25,7 +25,7 @@ const
isIOS = /iP(?:ad|hone)/.test(ua) || (isMac && !!navigator.maxTouchPoints), isIOS = /iP(?:ad|hone)/.test(ua) || (isMac && !!navigator.maxTouchPoints),
isAndroid = /Android/.test(ua), isAndroid = /Android/.test(ua),
isWebKit = /WebKit\//.test(ua), isWebKit = /WebKit\//.test(ua),
ctrlKey = isMac ? 'meta-' : 'ctrl-', ctrlKey = isMac || isIOS ? 'meta-' : 'ctrl-',
cantFocusEmptyTextNodes = isWebKit, cantFocusEmptyTextNodes = isWebKit,
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space // Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
notWS = /[^ \t\r\n]/, notWS = /[^ \t\r\n]/,
@ -141,7 +141,7 @@ const
}, },
// source/node/Whitespace.ts // source/node/Whitespace.ts
notWSTextNode = node => isElement(node) ? node.nodeName === "BR" : notWS.test(node.data), notWSTextNode = node => isElement(node) ? isBrElement(node) : notWS.test(node.data),
isLineBreak = (br, isLBIfEmptyBlock) => { isLineBreak = (br, isLBIfEmptyBlock) => {
let walker, block = br.parentNode; let walker, block = br.parentNode;
while (isInline(block)) { while (isInline(block)) {
@ -224,7 +224,7 @@ const
while (!isTextNode(endContainer)) { while (!isTextNode(endContainer)) {
child = endContainer.childNodes[endOffset - 1]; child = endContainer.childNodes[endOffset - 1];
if (!child || isLeaf(child)) { if (!child || isLeaf(child)) {
if (child?.nodeName === "BR" && !isLineBreak(child)) { if (isBrElement(child) && !isLineBreak(child)) {
--endOffset; --endOffset;
continue; continue;
} }
@ -267,7 +267,7 @@ const
} }
while (endContainer !== endMax && endContainer !== root) { while (endContainer !== endMax && endContainer !== root) {
if (!isTextNode(endContainer) && endContainer.childNodes[endOffset]?.nodeName === "BR" && !isLineBreak(endContainer.childNodes[endOffset])) { if (!isTextNode(endContainer) && isBrElement(endContainer.childNodes[endOffset]) && !isLineBreak(endContainer.childNodes[endOffset])) {
++endOffset; ++endOffset;
} }
if (endOffset !== getLength(endContainer)) { if (endOffset !== getLength(endContainer)) {
@ -331,7 +331,7 @@ const
let wrapper, isBR; let wrapper, isBR;
// Not live, and fast // Not live, and fast
[...container.childNodes].forEach(child => { [...container.childNodes].forEach(child => {
isBR = child.nodeName === "BR"; isBR = isBrElement(child);
if (!isBR && child.parentNode == root && isInline(child) if (!isBR && child.parentNode == root && isInline(child)
// && (blockTag !== "DIV" || (child.matches && !child.matches(phrasingElements))) // && (blockTag !== "DIV" || (child.matches && !child.matches(phrasingElements)))
) { ) {
@ -448,7 +448,7 @@ const
offset = block.childNodes.length; offset = block.childNodes.length;
// Remove extra <BR> fixer if present. // Remove extra <BR> fixer if present.
const last = block.lastChild; const last = block.lastChild;
if (last?.nodeName === "BR") { if (isBrElement(last)) {
last.remove(); last.remove();
--offset; --offset;
} }
@ -1013,7 +1013,7 @@ const
// Ensure root has a block-level element in it. // Ensure root has a block-level element in it.
const child = root.firstChild; const child = root.firstChild;
if (!child || child.nodeName === "BR") { if (!child || isBrElement(child)) {
fixCursor(root); fixCursor(root);
root.firstChild && range.selectNodeContents(root.firstChild); root.firstChild && range.selectNodeContents(root.firstChild);
} }
@ -1220,7 +1220,7 @@ const
textContent += value; textContent += value;
addedTextInBlock = true; addedTextInBlock = true;
} }
} else if (node.nodeName === "BR" || addedTextInBlock && !isInline(node)) { } else if (isBrElement(node) || addedTextInBlock && !isInline(node)) {
textContent += "\n"; textContent += "\n";
addedTextInBlock = false; addedTextInBlock = false;
} }
@ -1452,7 +1452,7 @@ const
// it removes the div and replaces it with just a <br> inside the // it removes the div and replaces it with just a <br> inside the
// root. Detach the <br>; the _ensureBottomLine call will insert a new // root. Detach the <br>; the _ensureBottomLine call will insert a new
// block. // block.
if (node === self._root && (node = node.firstChild) && node.nodeName === "BR") { if (node === self._root && (node = node.firstChild) && isBrElement(node)) {
detach(node); detach(node);
} }
self._ensureBottomLine(); self._ensureBottomLine();
@ -1736,7 +1736,7 @@ const
range = createRange(root.insertBefore( range = createRange(root.insertBefore(
this.createDefaultBlock(), nextElement this.createDefaultBlock(), nextElement
), 0); ), 0);
if (nextElement.tagName === "BR") { if (isBrElement(nextElement)) {
// delete it because a new <br> is created by createDefaultBlock() // delete it because a new <br> is created by createDefaultBlock()
root.removeChild(nextElement); root.removeChild(nextElement);
} }
@ -1795,6 +1795,8 @@ const
isElement = node => node instanceof Element, isElement = node => node instanceof Element,
isTextNode = node => node instanceof Text, isTextNode = node => node instanceof Text,
// isBrElement = node => node instanceof HTMLBRElement,
isBrElement = node => "BR" === node?.nodeName,
createTreeWalker = (root, whatToShow, filter) => { createTreeWalker = (root, whatToShow, filter) => {
const walker = doc.createTreeWalker(root, whatToShow, filter ? { const walker = doc.createTreeWalker(root, whatToShow, filter ? {
@ -2045,14 +2047,6 @@ const
let nodeCategoryCache = new WeakMap(); let nodeCategoryCache = new WeakMap();
// System standard for page up/down on Mac is to just scroll, not move the
// cursor. On Linux/Windows, it should move the cursor, but some browsers don't
// implement this natively. Override to support it.
if (!isMac && !isIOS) {
keyHandlers.pageup = self => self._moveCursorTo(true);
keyHandlers.pagedown = self => self._moveCursorTo(false);
}
keyHandlers[ctrlKey + "b"] = mapKeyToFormat("B"); keyHandlers[ctrlKey + "b"] = mapKeyToFormat("B");
keyHandlers[ctrlKey + "i"] = mapKeyToFormat("I"); keyHandlers[ctrlKey + "i"] = mapKeyToFormat("I");
keyHandlers[ctrlKey + "u"] = mapKeyToFormat("U"); keyHandlers[ctrlKey + "u"] = mapKeyToFormat("U");
@ -2288,6 +2282,14 @@ class Squire
this.setStyle({fontFamily:event.data}); this.setStyle({fontFamily:event.data});
}, },
/* /*
formatIndent: event => {
event.preventDefault();
this.changeIndentationLevel("increase");
},
formatOutdent: event => {
event.preventDefault();
this.changeIndentationLevel("decrease");
},
// deleteByCut: event => { // deleteByCut: event => {
this.saveUndoState(); this.saveUndoState();
}, },
@ -2301,9 +2303,11 @@ class Squire
} }
} }
// https://rawgit.com/w3c/input-events/v1/index.html#interface-InputEvent-Attributes // https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/inputType
// https://github.com/w3c/input-events
_beforeInput(event) { _beforeInput(event) {
let type = event.inputType; let type = event.inputType;
// event.getTargetRanges();
switch (type) { switch (type) {
case "formatBold": case "formatBold":
case "formatItalic": case "formatItalic":
@ -2567,14 +2571,6 @@ class Squire
return getClosest(this.getSelection().commonAncestorContainer, this._root, selector); return getClosest(this.getSelection().commonAncestorContainer, this._root, selector);
} }
// ---
_moveCursorTo(toStart) {
const root = this._root,
range = createRange(root, toStart ? 0 : root.childNodes.length);
moveRangeBoundariesDownTree(range);
this.setSelection(range);
}
// --- Path // --- Path
getPath() { getPath() {
@ -3013,7 +3009,7 @@ class Squire
range.commonAncestorContainer, range.commonAncestorContainer,
SHOW_ELEMENT_OR_TEXT, SHOW_ELEMENT_OR_TEXT,
node => (isTextNode(node) || node => (isTextNode(node) ||
node.nodeName === "BR" || isBrElement(node) ||
node.nodeName === "IMG" node.nodeName === "IMG"
) && isNodeContainedInRange(range, node) ) && isNodeContainedInRange(range, node)
); );
@ -3368,13 +3364,13 @@ class Squire
} }
while (isTextNode(child) && !child.data) { while (isTextNode(child) && !child.data) {
next = child.nextSibling; next = child.nextSibling;
if (!next || next.nodeName === "BR") { if (!next || isBrElement(next)) {
break; break;
} }
detach(child); detach(child);
child = next; child = next;
} }
if (!child || child.nodeName === "BR" || isTextNode(child)) { if (!child || isBrElement(child) || isTextNode(child)) {
break; break;
} }
nodeAfterSplit = child; nodeAfterSplit = child;