iT邦幫忙

0

不使用 innerHTML 改變文字樣式

  • 分享至 

  • xImage

各位大大好,
小弟正在開發一個自用的文字處理相關的 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() 來改變特定文字的樣式?

淺水員 iT邦大師 6 級 ‧ 2022-07-25 14:50:01 檢舉
內文有允許 html 語法嗎(例如改變顏色、樣式、允許超連結等)?
還是只允許純文字?
froce iT邦大師 1 級 ‧ 2022-07-25 16:22:19 檢舉
有允許html就真的建議用XSS lib做了。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
前端野人
iT邦新手 3 級 ‧ 2022-07-24 23:26:41

目前看來最適合的方式是用 前端框架,現在主流的前端框架都會擋XSS,然後也有套件能幫你改寫內容:
https://www.npmjs.com/package/react-html-replace

你要改樣式的方式會用到 innerHTML 如果要擋XSS就要把html轉成字串,所以照你的範例來看的話

目前你現階段可能解法:
1.先將文字過濾掉任何可以組成程式碼的字串
2.後端阻擋

0
froce
iT邦大師 1 級 ‧ 2022-07-25 08:28:43
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。

我要發表回答

立即登入回答