简单地写了一下, 还可以继续优化, 不过这样应该够用了.
function isText(target, node) {
return target !== null && target.nodeType === Node.TEXT_NODE
&& node.nodeType === Node.TEXT_NODE
}
function shouldMerge(target, node) {
if (target === null) {
return false
}
return target.nodeType === Node.ELEMENT_NODE
&& node.nodeType === Node.ELEMENT_NODE
&& node.getAttribute('class') === target.getAttribute('class')
}
/**
* @
param rootNode {Node}
*/
function mergeChildrenNodes(rootNode) {
if (!rootNode.hasChildNodes()) {
return;
}
let preChild = rootNode.firstChild;
const markToRemove = []
for (let i = 1; i < rootNode.childNodes.length; i++) {
const child = rootNode.childNodes[i];
if (isText(preChild, child)) {
preChild.textContent += child.textContent;
markToRemove.push(child);
} else if (shouldMerge(preChild, child)) {
child.childNodes.forEach(node => preChild.appendChild(node));
markToRemove.push(child);
} else {
preChild = child;
}
}
markToRemove.forEach(node => node.parentNode.removeChild(node));
for (const node of rootNode.childNodes) {
mergeChildrenNodes(node);
}
}
function test() {
const dom = new DOMParser().parseFromString(`<\span>高<\/span>
<\span class="del">情<\/span>
<\span class="del">已<\/span>
<\span class="match"><\span class="add">逐<\/span><\span class="add">晓<\/span><\/span>
<\span class="match"><\span>云</span><\span>空</span><\/span>`, 'text/html')
mergeChildrenNodes(dom)
const theSpanWitchClassIsDel = dom.lastChild.lastChild.childNodes[1];
console.info(theSpanWitchClassIsDel)
console.assert(theSpanWitchClassIsDel.getAttribute)
console.assert(theSpanWitchClassIsDel.textContent === '情已')
}