У меня есть следующая строка html,
<p>
a
<i>
b
<u>
c X d
</u>
e
</i>
f
</p>
Я бы хотел развернуть тег <i>
вокруг X
, оставив остальной текст с собственными тегами. другими словами, я хочу обернуть b, c, d и e тегом <i>
, получая при этом X. Например, это должно выглядеть так:
<p>
a
<i>
b
<u>
c
</u>
</i>
<u>
X
</u>
<i>
<u>
d
</u>
e
</i>
f
</p>
Это то, что я сделал, все работает нормально, но мне было интересно, есть ли лучший способ сделать это.
function unwrapX(htmlText) {
if(!htmlText.includes('X')){
return htmlText;
}
var div = document.createElement('div');
div.innerHTML = htmlText;
var arr = [];
div.querySelectorAll("p").forEach(function(p){
p.innerHTML = p.innerHTML.replace(/X/g, "<dummy>X</dummy>");
var item = p.querySelector("dummy");
while(item) {
arr.push([]);
var it = item
while(it.nodeName !== "P"){
if(it.nodeName !== "DUMMY"){
var clonedNode = it.cloneNode();
arr[arr.length-1].push(clonedNode)
}
it = it.parentNode
}
item.outerHTML = "<temp id=\"" + (arr.length-1).toString() + "\">" + item.innerHTML + "</temp>"
item = p.querySelector("dummy");
}
})
Array.from(div.querySelectorAll('*:empty')).forEach(el=>{el.remove();});
div.querySelectorAll("temp").forEach(function(temp){
var id = temp.id;
var wrappers = arr[id];
var closeAll = "";
for(var i = 0; i < wrappers.length; i++){
closeAll += wrappers[i].outerHTML.match(/<\/[a-zA-Z]+(>|.*?[^?]>)/g)[0];
}
var openAllButI = "";
for(var i = wrappers.length-1; i >= 0; i--){
if(wrappers[i].nodeName === "I") continue;
openAllButI += wrappers[i].outerHTML.match(/<[a-zA-Z]+(>|.*?[^?]>)/g)[0];
}
var closeAllButI = "";
for(var i = 0; i < wrappers.length; i++){
if(wrappers[i].nodeName === "I") continue;
closeAllButI += wrappers[i].outerHTML.match(/<\/[a-zA-Z]+(>|.*?[^?]>)/g)[0];
}
var openAll = "";
for(var i = wrappers.length-1; i >= 0; i--){
openAll += wrappers[i].outerHTML.match(/<[a-zA-Z]+(>|.*?[^?]>)/g)[0];
}
var replaceOpen = closeAll + openAllButI;
var replaceClose = closeAllButI + openAll;
var orig = temp.outerHTML;
var repl = replaceOpen + "X" + replaceClose;
div.innerHTML = div.innerHTML.replace(orig, repl)
});
while(div.querySelectorAll('*:empty').length > 0){
Array.from(div.querySelectorAll('*:empty')).forEach(el=>{el.remove();})
}
return div.innerHTML;
}
}