UNPKG

@ge-ge/highlight

Version:
226 lines (218 loc) 6.65 kB
/** * 递归获取nodeList内元素,如果元素内只有文本,则不继续深一层遍历 * @param df * @param deep 是否深一层遍历,元素内只有文本的元素 */ export function getNodeList( df: DocumentFragment | Node | Element, deep = false, ) { function recursion(node: Element | Node) { const list: Node[] = []; const pushToList = (list: Node[], pNode: Node | Node[]) => { if (pNode instanceof Array) { list.push(...pNode); } else { list.push(pNode); } }; if (node.nodeType === Node.TEXT_NODE) { pushToList(list, node); return list; } else if ( node.nodeType === Node.ELEMENT_NODE && 'childElementCount' in node && node.childElementCount === 0 && !deep ) { pushToList(list, node); return list; } else { // NodeList is not an Array, NodeList才有所有信息 const length = node.childNodes.length; for (let i = 0; i < length; i++) { const item = node.childNodes[i]; if (item.nodeType !== Node.TEXT_NODE) { const list2 = recursion(item); pushToList(list, list2); } else { pushToList(list, item); } } return list; } } return recursion(df); } function nextSibling( ele: DocumentFragment | Node | Element | ParentNode, root?: Node | Element, // eslint-disable-next-line no-unused-vars cb?: (list2: Node[]) => any, ) { const list: Node[] = []; if (ele.nextSibling) { list.push(ele.nextSibling); const list2 = nextSibling(ele.nextSibling, root); list.push(...list2); cb && cb(list2); } else if ( root && ele.parentNode && ele.parentNode !== root && ele.parentNode.parentNode !== root ) { const list2 = nextSibling(ele.parentNode, root); list.push(...list2); cb && cb(list2); } return list; } function previousSibling( ele: DocumentFragment | Node | Element | ParentNode, root?: Node | Element, // eslint-disable-next-line no-unused-vars cb?: (list2: Node[]) => any, ) { const list: Node[] = []; if (ele.previousSibling) { list.unshift(ele.previousSibling); const list2 = previousSibling(ele.previousSibling, root); list.unshift(...list2); cb && cb(list2); } else if ( root && ele.parentNode && ele.parentNode !== root && ele.parentNode.parentNode !== root ) { const list2 = previousSibling(ele.parentNode, root); list.unshift(...list2); cb && cb(list2); } return list; } function getPath( ele: DocumentFragment | Node | Element | ParentNode, root?: Node | Element, ) { const path: ParentNode[] = []; const r = (ele: DocumentFragment | Node | ParentNode | Element) => { if (ele !== root && ele.parentNode && ele.parentNode !== root) { path.push(ele.parentNode); r(ele.parentNode); } }; r(ele); return path; } /** * @description 将Range分成开头、结尾部分 * @return Array * */ export function splitRange(range: Range) { const ranges: { start?: { id: string; range: Range }; end?: { id: string; range: Range }; } = {}; const start: Range = document.createRange(); const end: Range = document.createRange(); // 当开头结尾为同一个元素时 if (range.startContainer === range.endContainer) { start.setStart(range.startContainer, range.startOffset); start.setEnd(range.endContainer, range.endOffset); } else { if (range.startContainer) { start.setStart(range.startContainer, range.startOffset); if (range.startContainer.nodeType === Node.TEXT_NODE) { start.setEndAfter(range.startContainer); } else { start.setEnd( range.startContainer, range.startContainer.childNodes.length, ); } } end.setStart(range.endContainer, 0); end.setEnd(range.endContainer, range.endOffset); } ranges.start = { id: 'start', range: start, }; ranges.end = { id: 'end', range: end, }; return ranges; } export function splitRange2(range: Range) { const { startContainer, endContainer, commonAncestorContainer } = range; if (startContainer === endContainer) { return []; } if ( startContainer && endContainer && startContainer.parentNode === endContainer.parentNode ) { const range: Range = document.createRange(); range.setStartAfter(startContainer); range.setEndBefore(endContainer); return [range]; } function createRange(list: Node[]) { const range: Range = document.createRange(); range.setStartBefore(list[0]); range.setEndAfter(list[list.length - 1]); return range; } // 从startContainer 开始遍历 const startSiblingList: Range[] = []; nextSibling(startContainer, commonAncestorContainer, (list) => { if (list && list.length) startSiblingList.push(createRange(list)); }); const endSiblingList: Range[] = []; previousSibling(endContainer, commonAncestorContainer, (list) => { if (list && list.length) endSiblingList.push(createRange(list)); }); const centerList = []; let isStart = false; if (commonAncestorContainer.childNodes.length > 2) { const sPath = getPath(startContainer, commonAncestorContainer); const ePath = getPath(endContainer, commonAncestorContainer); for (let i = 0; i < commonAncestorContainer.childNodes.length - 1; i++) { const item = commonAncestorContainer.childNodes[i]; if (item === <Node>sPath[sPath.length - 1]) { isStart = true; continue; } if (!isStart) continue; if (item === <Node>ePath[ePath.length - 1]) { break; } centerList.push(item); } } if (centerList.length) { const centerRangeList = createRange(centerList); return [...startSiblingList, centerRangeList, ...endSiblingList]; } return [...startSiblingList, ...endSiblingList]; } // eslint-disable-next-line no-unused-vars export function customMark(range: Range, cb: (arg0: DocumentFragment) => any) { const { start, end } = splitRange(range); const new_range_list = splitRange2(range); // 分割成多个range if (start && start.range) new_range_list.unshift(start.range); if (end && end.range) new_range_list.push(end.range); for (const new_range of new_range_list) { if (!new_range) continue; const docFragment = new_range.extractContents(); // 将选区内的元素移出到documentFragment // 对docFragment进行处理 cb && cb(docFragment); // 处理完成后插入到对应的range,range被修改没有参考意义 new_range.deleteContents(); new_range.insertNode(docFragment); } }