import { Type } from '@ephox/katamari'; import { SugarElement } from '@ephox/sugar'; import DOMUtils from '../api/dom/DOMUtils'; import DomTreeWalker from '../api/dom/TreeWalker'; import * as ElementType from './ElementType'; import { isContent } from './Empty'; import * as NodeType from './NodeType'; const isSpan = (node: Node): node is HTMLSpanElement => node.nodeName.toLowerCase() === 'span'; const isInlineContent = (node: Node | null, root: Node): boolean => Type.isNonNullable(node) && (isContent(node, root) || ElementType.isInline(SugarElement.fromDom(node))); const surroundedByInlineContent = (node: Node, root: Node): boolean => { const prev = new DomTreeWalker(node, root).prev(false); const next = new DomTreeWalker(node, root).next(false); // Check if the next/previous is either inline content or the start/end (eg is undefined) const prevIsInline = Type.isUndefined(prev) || isInlineContent(prev, root); const nextIsInline = Type.isUndefined(next) || isInlineContent(next, root); return prevIsInline && nextIsInline; }; const isBookmarkNode = (node: Node): boolean => isSpan(node) && node.getAttribute('data-mce-type') === 'bookmark'; // Keep text nodes with only spaces if surrounded by spans. // eg. "
a b
" should keep space between a and b const isKeepTextNode = (node: Node, root: Node): boolean => NodeType.isText(node) && node.data.length > 0 && surroundedByInlineContent(node, root); // Keep elements as long as they have any children const isKeepElement = (node: Node): boolean => NodeType.isElement(node) ? node.childNodes.length > 0 : false; const isDocument = (node: Node): boolean => NodeType.isDocumentFragment(node) || NodeType.isDocument(node); // W3C valid browsers tend to leave empty nodes to the left/right side of the contents - this makes sense // but we don't want that in our code since it serves no purpose for the end user // For example splitting this html at the bold element: //text 1CHOPtext 2
// would produce: //text 1
CHOPtext 2
// this function will then trim off empty edges and produce: //text 1
CHOPtext 2
const trimNode =