mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-11-10 17:13:38 +08:00
Improve Squire with isBrElement()
This commit is contained in:
parent
98b203a3ca
commit
508f5cc6e5
1 changed files with 26 additions and 30 deletions
56
vendors/squire/build/squire-raw.js
vendored
56
vendors/squire/build/squire-raw.js
vendored
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue