用 TS + Vue 写了一个在 Chrome 中运行 Prettier 格式化的扩展程序
在介紹 prettier-chrome 之前請允許我先介紹一下什么是 Prettier
如果你已經知道這是什么了并且已經會配置了,那么你可以直接跳到 prettier-chrome 的介紹
什么是 Prettier ?
- 有見識的代碼格式化工具
- 支持多種語言
- 與大多數編輯器集成
- 零配置,開箱即用(但你也可以少量配置)
為什么使用 Prettier ?
- 保存時自動格式化
- 無需在代碼審查中討論風格
- 節省您的時間和精力
- 和更多
支持的語言
JavaScript
- ES2017
- JSX
- Flow
- TypeScript
- Vue
- JSON
CSS
- CSS3+
- Less
- SCSS
- styled-components
- styled-jsx
GraphQL
- GraphQL
- GraphQL Schemas
Markdown
- CommonMark
- GitHub Flavored Markdown
Work in Progress
- Elm (via elm-format)
- Java
- PHP
- PostgreSQL
- Python
- Ruby
- Swift
支持的編輯器
- Atom (prettier-atom / mprettier / miniprettier)
- Emacs (prettier-emacs)
- Espresso (espresso-prettier)
- Sublime Text (JsPrettier)
- Vim (neoformat / ale / vim-prettier)
- Visual Studio (JavaScriptPrettier)
- VS Code (prettier-vscode)
- WebStorm (Built-in support)
可以看到 Prettier 是一個非常強大的格式化程序,目前唯一的缺陷是暫時還不支持格式化 HTML 文件
因為 HTML 的情況比較復雜,它還需要考慮 Vue 和 Angular 的模版語法,不過這已經在計劃中了
大家可以在 Playgournd 中體驗 Prettier 的所有功能:
食用 Prettier 的正確姿勢
在這里向大家介紹一下如何正確使用 Prettier 來統一代碼風格
1. 如何結合 ESLint 使用?
如果你想與 ESLint 結合使用,那么有兩個方案:
我希望格式化結果完全符合 Prettier 的要求
eslint-plugin-prettier 的工作原理是,對比格式化前和用 Prettier 格式化后的代碼,有不一致的地方就會報錯,然后你可以手動運行 eslint --fix 來修復。
不過 Prettier 的格式化很可能和你使用的 ESLint 配置沖突,比如你的 ESLint 設定的不使用分號,而 Prettier 默認使用分號,這時候你需要配置 Prettier 讓它不使用分號。反之如果你想使用 Prettier 的規則而不是 ESLint 的,為防止 ESLint 報錯,你需要使用 eslint-config-prettier 來關閉所有可能引起沖突的規則。
{"scripts": {"lint": "eslint *.js"},"eslintConfig": {"extends": ["prettier"],"plugins": ["prettier"],"rules": {"prettier/prettier": "error"}},"prettier": {"singleQuote": true,"semi": false} } 復制代碼你可以使用大多數編輯器里 ESLint 插件提供的 autoFixOnSave 選項來在保存時自動格式化。
希望格式化結果完全符合 ESLint 的要求(推薦)
使用 ESLint 與 eslint-plugin-prettier 的結果是最終得到的代碼是充分尊重 Prettier 的結果,而 prettier-eslint-cli 則是先執行 Prettier 然后再自動使用 eslint --fix 將與 ESLint 規則沖突的代碼修正成 ESLint 想要的結果。這樣其實引入 Prettier 不會影響你原有的設置。
{"scripts": {// ESLint 只負責檢查代碼質量"lint": "eslint *.js",// 用 Prettier 格式化代碼并自動 `eslint --fix `以便下次執行 `npm run lint` 時不會報錯"format": "prettier-eslint --write *.js"},"eslintConfig": {"extends": "some-config"},"prettier": {"singleQuote": true,"semi": false} } 復制代碼除了命令行的 npm run format,同時你也可以使用編輯器里的 Prettier 插件,并啟用 eslintIntegration 來在編輯器里自動格式化代碼。
這一段摘自 EGOIST 大佬的博客《用 ESLint 和 Prettier 寫出高質量代碼》
原文地址:https://egoist.moe/2017/12/11/write-better-code-with-eslint-and-prettier
這里我想讓大家注意一點,就是 eslint 和 prettier 命令的匹配參數最好加上雙引號,否則可能出現錯誤。
2. 使用 gitHooks 在提交代碼時自動格式化
Q: 為什么要使用提交鉤子?我編輯器已經安裝了 prettier 插件了,豈不是多此一舉?
A: 如果是你的個人項目那么無所謂。如果是多人開發或者開源項目的話,你不能保證所有人都安裝編輯器插件,所以需要使用 gitHooks 來保證風格統一。
安裝 yorkie 和 lint-staged 來配置提交鉤子
yarn add yorkie lint-staged --dev 復制代碼yorkie 是尤大 fork 自 husky 進行少量更改的提交鉤子,在 @vue/cli 3.x 中內置。
當然,別忘了安裝 prettier 模塊
yarn add prettier --dev 復制代碼安裝好了之后在 package.json 中的 gitHooks 和 lint-staged 屬性中配置提交鉤子
{"gitHooks": {"pre-commit": "lint-staged"},"lint-staged": {"*.{ts,tsx,js,jsx,json,scss,md}": ["prettier --write", "git add"]} } 復制代碼正常情況下安裝 yorkie 后會自動安裝提交鉤子
如果提交鉤子未生效可以手動運行 node node_modules/yorkie/bin/install.js 來安裝。
當然,你也可以運行 node node_modules/yorkie/bin/uninstall.js 來卸載提交鉤子。
3. 在 CI 上檢查代碼是否忘記格式化
Q: 我已經配置了 gitHooks 了,為什么還要在 CI 上檢查?豈不是多此一舉?
A: 是的,gitHooks 可以保證大部分情況。但是別忘了,如果別人直接在 Github 上提交代碼的話是沒有提交鉤子的哦。
安裝 prettier 和 prettier-check 來檢查是否忘記格式化代碼
yarn add prettier prettier-check --dev 復制代碼安裝好了之后在 package.json 中的 scripts 屬性中配置如下:
{"scripts": {"lint:prettier": "prettier-check \"**/*.{ts,tsx,js,jsx,json,scss,md}\"","format": "prettier \"**/*.{ts,tsx,js,jsx,json,scss,md}\" --write"} } 復制代碼接下來你就可以使用 yarn lint:prettier 來檢查是否忘記格式化代碼了
同時你可以使用 yarn format 來格式化所有匹配的文件
接下來配置 CI,以 Travis CI 為例子,配置如下:
language: node_jsnode_js: 9install: - yarnscript: - yarn lint - yarn lint:prettiercache: yarn: true directories: - node_modules 復制代碼這樣當你提交代碼后 Travis 就會運行檢查命令,以保證代碼風格統一。
同時如果有人給你的項目 Pull request,也會進行檢查,檢查失敗可以要求對方更改后再提交。
不過 prettier-check 只適用于“希望格式化結果完全符合 Prettier 的要求”的場景。所以我 fork 了一份 prettier-check 修改成了 prettier-eslint-check 可以用來檢查“希望格式化結果完全符合 ESLint 的要求”的場景,只需要把 prettier-check 改成 prettier-eslint-check 即可。
yarn add prettier prettier-eslint-{cli,check} --dev 復制代碼{"scripts": {"lint:prettier":"prettier-eslint-check \"**/*.{ts,tsx,js,jsx,json,scss,md}\"","format": "prettier-eslint \"**/*.{ts,tsx,js,jsx,json,scss,md}\" --write"} } 復制代碼prettier-check 和 prettier-eslint-check 的使用方式和 prettier 一致,只是去掉了 --write 參數
prettier-chrome
好了,Prettier 的介紹和使用方式都已經說了,接下來我要來介紹一下我寫的 prettier-chrome 擴展了!
先給大家放一張動態圖,相信看完之后大家就知道是干嘛用的了!
沒錯!這是一款可以讓 Prettier 運行在 Chrome 的擴展程序!
它主要用來在線寫 markdown 時格式化,適用于:
- sf.gg 答題
- gayhub 提 issues、pr
- 在線寫博客
- 等等...
主要功能:
- 中英文之間自動添加空格
- 自動對齊表格
- 自動對齊列表
- 代碼塊指定的語言如果支持的話會使用對應的 parser 格式化
- 等等...
用法非常簡單,你只需要在 markdown 編輯器獲得焦點的時候按下 ALT + F 快捷鍵即可格式化!
可以配置 Prettier 中的所有選項
這個擴展是基于昨天發布的 Prettier v1.13.0 版本進行開發的,這個項目我已經蓄謀已久了,無奈之前版本的 Prettier 并不支持在瀏覽器中運行,所以我一直在關注 Prettier 的動態,終于在昨天 v1.13.0 發布,并支持在瀏覽器中運行!于是老夫我擼起袖子就是一頓干,然后申請把項目添加到 Prettier 官網中,并得到了官方人員的認可!
官方還轉推了 (?>?<?)
我絕對沒有膨脹,我沒有!(留下了沒有技術的淚水,逃
順便問一句,大家有沒有覺得我這篇文章的排版特別舒服呀?這都是 Prettier 的功勞喲(
擴展的原理非常簡單,popup 頁面用來修改 Prettier 的各種選項并保存到 localStorage 中。
在背景頁面(事件頁面)注冊右鍵菜單和快捷鍵命令,通過 chrome.tabs.sendMessage 與內容腳本通信。
在內容腳本通過 chrome.runtime.onMessage 監聽消息,如果收到了格式化指令則獲取當前獲得焦點的元素判斷是否是一個多行文本框,如果是并且內容不為空則調用 prettier.format 方法將當前元素的內容和插件還有 localStorage 中保存的選項傳遞給它,獲得格式化的結果后重新賦值文本框。
源碼在這里:https://github.com/u3u/prettier-chrome
官方人員已 star,請各位放心食用(
歡迎各種 pr 和 review,喜歡的話別忘了點個 star 喲 (* >ω<)
項目架構
當然是選擇原諒色的 Vue 啦!
使用 @vue/cli 3.0.0-beta.12 生成一個 TS + Vue 全家桶的項目
- 使用 ESLint 代替 TSLint
- 使用渲染函數 JSX 代替模版
- 使用 vue-emotion CSS in JavaScript 方案
使用 ESLint 代替 TSLint 的理由
ESLint 規則比 TSLint 多,并且有主流的規則可以選擇
使用 JSX 代替模版的理由
- Prettier 暫不支持格式化 HTML
- 使用渲染函數讓你對 Vue 的理解更深
- JSX 比模版更靈活
- JSX 的開發體驗比模版好(雖然現在 VSC 有 Vetur 擴展支持,但依然無法達到 JSX 的程度)
- JSX 不限制你的標簽名(媽媽再也不用擔心我起的名和 HTML 內置標簽名重復的問題啦)
當然了,JSX 對初學者不友好。我初學 Vue 的時候都是跳過渲染函數這一節看的 ?
使用 vue-emotion CSS in JavaScript 方案的理由
因為已經使用 JSX 代替模版了,當然希望和單文件組件一樣把 CSS 也寫在一起啦!
不過我研究了很多 CSS in JavaScript 的庫,基本都不支持 PostCSS 插件。除了 styled-jsx,不過它只支持 React。所以正規項目最好不要使用,可以使用 CSS Modules 的方案代替(但這就需要將 CSS 文件從 JS 中分離出來了)。
使用 Vue 只是為了方便寫擴展的 popup 頁面或者 option 頁面
使用 Vue-Router 來切換頁面,無需多入口打包。
而背景頁面(事件頁面)和內容腳本都是無頁面的,只需要腳本,所以我使用 bili 來打包。
bili
bili 是 egoist 大佬基于 rollup 封裝的一個零配置打包工具。
egoist 大佬是 vue-cli 的核心開發者之一,大家可以放心使用。
順便說一句,3.x 的 vue-cli 借鑒了很多 egoist 大佬的想法,詳情:https://github.com/vuejs/vue-cli/issues/589
參考文檔:https://bili.egoist.moe/#/api
CSP(內容安全策略)
在 Chrome 擴展中使用 Vue 只有一個問題,那就是 CSP 的問題。這一點在 Vue 的文檔中也有說明。
在 Chrome 擴展環境中默認策略限制如下:
- eval 及相關函數已禁用(eval / setTimeout / setInterval / new Function)
- 內嵌 JavaScript 代碼將不會執行
- 只有本地腳本和對象資源才會加載
在我這個擴展中我使用放寬策略來讓 Vue 正常工作,在 manifest.json 中配置如下:
{"content_security_policy":"script-src 'self' 'unsafe-eval'; object-src 'self'" } 復制代碼但是這樣配置之后還有一個問題,因為 3.x 的 vue-cli 生成環境下打包出來的腳本是內嵌的
并且這個沒有放寬策略,于是我在 Issues 里搜索到了一個相同的問題:https://github.com/vuejs/vue-cli/issues/1074
通過配置 vue.config.js 刪除 split-manifest 和 inline-manifest 即可。
module.exports = {chainWebpack: (config) => {config.plugins.delete('split-manifest').delete('inline-manifest');}, }; 復制代碼參考文檔:https://crxdoc-zh.appspot.com/extensions/contentSecurityPolicy
如何開發一個 Chrome 擴展?
概述:https://crxdoc-zh.appspot.com/extensions/overview
清單文件格式:https://crxdoc-zh.appspot.com/extensions/manifest
JavaScript API:https://crxdoc-zh.appspot.com/extensions/api_index
總結
以上是生活随笔為你收集整理的用 TS + Vue 写了一个在 Chrome 中运行 Prettier 格式化的扩展程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python面试必知(四)
- 下一篇: Nuxt爬坑系列之vuex