我有一個字串和一個包含 N 項的陣列:
<div>
sometimes the fox can fly really high
</div>
const arr = ['the fox can', 'fox can fly', 'really high']`
我想找到一種方法用 HTML 替換 div 中的文本,以突出顯示陣列中的那些特定短語而不破壞 HTML。這可能是有問題的,因為我不能做一個簡單的回圈和替換,因為替換后其他單詞將不匹配,因為突出顯示跨度會破壞類似indexOf或includes的東西innerHTML,當然我可以用innerText它來閱讀文本但它沒有提供任何能夠做到這一點的東西,這樣我就可以添加“下一個”跨度而不會破壞原始的 HTML 高亮顯示。理想情況下,我還希望能夠根據我使用的單詞自定義類名,而不僅僅是一個通用的突出顯示類。
結果應該是
<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并且感覺真的很hacky,絕對不是性能,我只是得到一種“氛圍”,我不應該使用這種方法并且必須有更好的解決方案,我正在向SO尋求關于如何完成這個挑戰的想法.
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 hljs-subst">${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>")
}
uj5u.com熱心網友回復:
我將回顧你的例子只是為了給出一個想法。下面的代碼不是一個干凈的函式,請根據您的需要進行調整。
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 hljs-subst">${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 hljs-subst">${tmp}">`;
stack.push(tmp);
}
}
index = e.pos;
});
result = str.substring(index, str.length)
console.log(result);
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/426148.html
標籤:javascript html dom
