prettier
安裝 prettier(方式一)
首先,輸入以下指令來安裝 husky
, lint-staged
和 prettier
npm install --save husky lint-staged prettier
安裝好後,在 package.json 的任意位置加上這段:
husky 也是一個套件,lint-staged 也是一個套件
我在 commit 之前(pre-commit),我要執行 lint-staged
在執行 lint-staged
時,針對符合 src/**/*.{js,jsx,ts,tsx,json,css,scss,md}
這些規則的檔案,我要跑 prettier --write
(針對要 commit 的這些檔案執行 prettier --write
)
因為我不希望每次 commit 都對所有檔案做 prettier
,如果是已經 commit 過的檔案,就不需要再對它執行 prettier
了(已經 prettier
好了)
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/*.{js,jsx,ts,tsx,json,css,scss,md}": [
"prettier --write"
]
},
注意,在文件上寫的規則是 "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"
,這樣會是「src 底下的子資料夾底下的檔案」
但是,在我的專案中,App.js 這些檔案就直接是在「src 底下」,所以規則要改成 "src/*.{js,jsx,ts,tsx,json,css,scss,md}"
這樣,在每次 commit 時,就會幫我用 prettier
做 code formatting 了
安裝 prettier(方式二)
第二種方式是用 vs code 的 plugin 來安裝 prettier
在 Extensions 搜尋 Prettier - Code formatter
Format On Save
安裝好之後,我可以設定在存檔時跑 prettier
設定方式:
在 vs code 的 Settings 搜尋「Format On Save」,把「Format On Save」選項打勾
接著,在 Settings 搜尋「Default Formatter」> 選擇 esbenp.prettier-vscode
這樣,在每次存檔時,就會幫我用 prettier
做 code formatting 了
可參考 Format on Save (prettier) stopped working with latest update
JSX 特性
JSX 會自動幫我處理好 XSS 的問題(會自動幫我做 escape)
也就是說,我在欄位輸入 <h1>hello</h1>
按下新增,JSX 會用純文字顯示出來,而不會是 h1
的標籤
如果我真的就是要輸出 HTML 的標籤,就要啟用 dangerouslySetInnerHTML
這個功能
文件可參考 dangerouslySetInnerHTML
把 <TodoContent>
改成:
在 dangerouslySetInnerHTML={}
裡面傳入一個物件,物件裡面在 __html:
後面放我要 render 出來的內容 todo.content
return (
<TodoItemWrapper className={className} data-todo-id={todo.id}>
<TodoContent
$isFinished={todo.isFinished}
size={size}
dangerouslySetInnerHTML={{
__html: todo.content,
}}
></TodoContent>
這樣就可以輸出 HTML 標籤了(我在欄位輸入的內容,會真的變成 innerHTML
)
但要特別注意的是:React 內建無法防範在 <a></a>
的 click-based XSS
無論是否在寫 React,都要注意 click-based 的 XSS 的問題
例如:
我 render 出一個 a
連結 <a href={todo.content}>click me!</a>
todo.content
就是我在欄位輸入的內容
return (
<TodoItemWrapper className={className} data-todo-id={todo.id}>
<TodoContent $isFinished={todo.isFinished} size={size}>
{todo.content}
</TodoContent>
<a href={todo.content}>click me!</a>
然後,如果我在欄位輸入 javascript: alert('haha') 按下新增,當我點擊「click me!」這個 a
連結時,就會執行 javascript: alert(‘haha’)
這行 JavaScript(跳出 haha 的 alert)
「click-based 的 XSS」運用的特性就是:
在 a
連結的 href=""
裡面,如果用「javascript: 」就可以在點擊時執行 JavaScript 的程式碼
之所以 React 無法防範這個 click-based 的 XSS 是因為:
React 內建的防範只會幫我做 escape,只會跳脫 <
, >
, ''
, ""
這些特殊符號,並不會把冒號 :
做跳脫
用 window.encodeURIComponent()
來修正 click-based 的 XSS
用 window.encodeURIComponent()
把 todo.content
做編碼
<a href={window.encodeURIComponent(todo.content)}>click me!</a>
這樣,如果我輸入 javascript: alert(‘yo’) 按下新增,當我點擊「click me!」這個 a
連結時,javascript: alert(‘yo’) 會被編碼為 javascript%3A%20alert(‘yo’)
(會把冒號 :
做編碼)
因此,網頁會導向到 http://localhost:3000/javascript%3A%20alert(%E2%80%98yo%E2%80%99) ,但是並不會跳出 alert