各位大大好,
小弟正在開發一個自用的文字處理相關的 WebApp 作為練習,
其中想要有一項功能:依照規則(正規表示式)在整篇內文中搜尋特定的文字並改變其樣式。
附上簡短的範例(CodePen)
// 節錄重點部分
function testFunc() {
let target = document.getElementById("target");
target.innerHTML = target.innerText.replace(
/[a|e|i|o|u][a|e|i|o|u]/g,
'<span class="colorize">$&</span>'
);
}
目前的思路是先取得內文,
接著用 .replace()
配合正規表示式將符合條件的內容取代為附有 class
的 <span>
,
取代後的 <span>
就會套用 CSS 內的樣式了。
但是在我實際的 WebApp 中,
內文是可供使用者輸入的,
如此一來就顯得上述使用到 .innerHTML()
的解法很不安全了。
不知道各位前輩有沒有什麼方法,
可以不透過 .innerHTML()
來改變特定文字的樣式?
目前看來最適合的方式是用 前端框架,現在主流的前端框架都會擋XSS,然後也有套件能幫你改寫內容:
https://www.npmjs.com/package/react-html-replace
你要改樣式的方式會用到 innerHTML 如果要擋XSS就要把html轉成字串,所以照你的範例來看的話
目前你現階段可能解法:
1.先將文字過濾掉任何可以組成程式碼的字串
2.後端阻擋
function testFunc() {
const target = document.getElementById("target");
const innerText = target.innerText
const pat = /[a|e|i|o|u][a|e|i|o|u]/g
const matchedStr = innerText.match(pat)
const matchedDom = matchedStr.map((s)=>{
const dom = document.createElement('span')
dom.classList.add("colorize")
dom.innerText = s
return dom.outerHTML
})
const splitText = innerText.split(pat)
let result = ""
for (let i =0; i<=splitText.length;i++){
if (i<=matchedDom.length-1){
result += splitText[i] + matchedDom[i]
} else {
result += splitText[i]
}
}
target.innerHTML = result
}
這樣吧。
利用innerText去塞內容,不要直接用innerHTML。
合併部分的code應該會有問題,可能會卡在開頭或結尾就符合 pattern 的案例。(我沒測試)
實務上我應該會用editor去做,例如 Tiptap。