我有一个字符串和一个N项数组:
<div>
sometimes the fox can fly really high
</div>const arr = ['the fox can', 'fox can fly', 'really high']`我想找到一种方法,用HTML替换div中的文本,在不破坏HTML的情况下突出显示数组中的那些特定短语。这可能会有问题,因为我不能执行简单的循环和替换,因为其他单词在替换后将不匹配,因为突出显示范围会破坏类似于indexOf或innerHTML上的includes之类的内容,当然,我可以使用innerText读取文本,但它没有提供任何使其生效的内容,因此我可以在不破坏原始HTML高亮显示的情况下添加"next“跨度。理想情况下,我还希望能够根据我使用的单词来定制类名,而不仅仅是一个普通的突出显示类。
结果应该是
<div>
sometimes
<span class="highlight-1">the <span class="highlight-2">fox can</span></span><span class="highlight-2"> fly</span> <span class="highlight-3">really high</span>
</div>我试过什么?
我真的考虑过这个问题,在网上找不到任何资源来帮助解决这个场景和主要问题,目前,我还需要额外的价值,比如charStart和charEnd,我不喜欢这个解决方案,因为它依赖于使用DOMParser() API,而且它感觉非常笨拙,显然没有性能,我只是得到了一种“氛围”,我不应该这样做,而且肯定会有更好的解决方案,我正在寻求关于如何完成这一挑战的想法。
let text = `<p id="content">${content}</p>`
let parser = new DOMParser().parseFromString(text, "text/html")
for (const str of strings) {
const content = parser.querySelector("#content")
let descLength = 0
for (const node of content.childNodes) {
const text = node.textContent
let newTextContent = ""
for (const letter in text) {
let newText = text[letter]
if (descLength === str.charStart) {
newText = `<em class="highlight ${str.type}" data-id="${str.id}">${text[letter]}`
} else if (descLength === str.charEnd) {
newText = `${text[letter]}</em>`
}
newTextContent += newText
descLength++
}
node.textContent = newTextContent
}
// Replace the < with `<` and replace > with `>` to construct the HTML as text inside lastHtml
const lastHtml = parser
.querySelector("#content")
.outerHTML.split("<")
.join("<")
.split(">")
.join(">")
// Redefine the parser variable with the updated HTML and let it automatically correct the element structure
parser = new DOMParser().parseFromString(lastHtml, "text/html")
/**
* Replace the placeholder `<em>` element with the span elements to prevent future issues. We need the HTML
* to be invalid for it to be correctly fixed by DOMParser, otherwise the HTML would be valid and *not* render how we'd like it to
* Invalid => `<span>test <em>title </span>here</em>
* Invalid (converted) => `<span>test <em>title </em></span><em>here</em>
* Valid => `<span>test <span>title </span>here</span>
*/
parser.querySelector("#content").innerHTML = parser
.querySelector("#content")
.innerHTML.replaceAll("<em ", "<span ")
.replaceAll("</em>", "</span>")
}发布于 2022-02-11 01:15:13
我会重温你的例子,只是想给出一个想法。下面的代码不是一个干净的函数,请根据您的需要进行调整。
const str = "sometimes the fox can fly really high";
const arr = ['the fox can', 'fox can fly', 'really high'];
// First, find the indices of start and end positions for your substrings.
// Call them event points and push them to an array.
eventPoints = [];
arr.forEach((a, i) => {
let index = strLower.indexOf(a)
while (index !== -1) {
let tagClass = `highlight-${i}`
eventPoints.push({ pos: index, className: tagClass, eventType: "start" })
eventPoints.push({ pos: index + a.length, className: tagClass, eventType: "end" })
index = strLower.indexOf(a, index + 1)
}
return
});
// Sort the event points based on the position properties
eventPoints.sort((a, b) => a.pos < b.pos ? -1 : a.pos > b.pos ? 1 : 0);
// Init the final string, a stack and an index to keep track of the current position on the full string
let result = "";
let stack = [];
let index = 0;
// Loop over eventPoints
eventPoints.forEach(e => {
// concat the substring between index and e.pos to the result
result += str.substring(index, e.pos);
if (e.eventType === "start") {
// when there is a start event, open a span
result += `<span class="${e.className}">`;
// keep track of which span is opened
stack.push(e.className);
}
else {
// when there is an end event, close tags opened after this one, keep track of them, reopen them afterwards
let tmpStack = [];
while (stack.length > 0) {
result += "</span>";
let top = stack.pop();
if (top === e.className) {
break;
}
tmpStack.push(top);
}
while (tmpStack.length > 0) {
let tmp = tmpStack.pop();
result += `<span class="${tmp}">`;
stack.push(tmp);
}
}
index = e.pos;
});
result += str.substring(index, str.length)
console.log(result);https://stackoverflow.com/questions/71073444
复制相似问题