mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 15:23:29 -05:00
fe0dfdf6c4
This is a massive refactor to port Squire to TypeScript, fix a bunch of small bugs and modernise our tooling. The development was done on an internal repository, so apologies to anyone following externally for the commit dump; updates from here should come as real commits again. Co-authored-by: Joe Woods <woods@fastmailteam.com>
69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
import { ZWS, notWS } from '../Constants';
|
|
import { isInline } from './Category';
|
|
import { getLength } from './Node';
|
|
import { SHOW_ELEMENT_OR_TEXT, SHOW_TEXT, TreeIterator } from './TreeIterator';
|
|
|
|
// ---
|
|
|
|
const notWSTextNode = (node: Node): boolean => {
|
|
return node instanceof Element
|
|
? node.nodeName === 'BR'
|
|
: // okay if data is 'undefined' here.
|
|
notWS.test((node as CharacterData).data);
|
|
};
|
|
|
|
const isLineBreak = (br: Element, isLBIfEmptyBlock: boolean): boolean => {
|
|
let block = br.parentNode!;
|
|
while (isInline(block)) {
|
|
block = block.parentNode!;
|
|
}
|
|
const walker = new TreeIterator<Element | Text>(
|
|
block,
|
|
SHOW_ELEMENT_OR_TEXT,
|
|
notWSTextNode,
|
|
);
|
|
walker.currentNode = br;
|
|
return !!walker.nextNode() || (isLBIfEmptyBlock && !walker.previousNode());
|
|
};
|
|
|
|
// --- Workaround for browsers that can't focus empty text nodes
|
|
|
|
// WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=15256
|
|
|
|
// Walk down the tree starting at the root and remove any ZWS. If the node only
|
|
// contained ZWS space then remove it too. We may want to keep one ZWS node at
|
|
// the bottom of the tree so the block can be selected. Define that node as the
|
|
// keepNode.
|
|
const removeZWS = (root: Node, keepNode?: Node): void => {
|
|
const walker = new TreeIterator<Text>(root, SHOW_TEXT);
|
|
let textNode: Text | null;
|
|
let index: number;
|
|
while ((textNode = walker.nextNode())) {
|
|
while (
|
|
(index = textNode.data.indexOf(ZWS)) > -1 &&
|
|
// eslint-disable-next-line no-unmodified-loop-condition
|
|
(!keepNode || textNode.parentNode !== keepNode)
|
|
) {
|
|
if (textNode.length === 1) {
|
|
let node: Node = textNode;
|
|
let parent = node.parentNode;
|
|
while (parent) {
|
|
parent.removeChild(node);
|
|
walker.currentNode = parent;
|
|
if (!isInline(parent) || getLength(parent)) {
|
|
break;
|
|
}
|
|
node = parent;
|
|
parent = node.parentNode;
|
|
}
|
|
break;
|
|
} else {
|
|
textNode.deleteData(index, 1);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// ---
|
|
|
|
export { isLineBreak, removeZWS };
|