prettier 和 JSX 特性


Posted by saffran on 2021-02-25

prettier

可參考文件 Formatting Code Automatically

安裝 prettier(方式一)

首先,輸入以下指令來安裝 husky, lint-stagedprettier

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(方式二)

可參考文件 Prettier - Code formatter

第二種方式是用 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)

文件可參考 JSX Prevents Injection Attacks

也就是說,我在欄位輸入 <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


#React







Related Posts

動態產生呼叫 modal

動態產生呼叫 modal

關於 React 小書:React props

關於 React 小書:React props

Fetch 與 Promise

Fetch 與 Promise


Comments