用 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 来切换页面,无需多入口打包。
{"browser_action": {"default_popup": "index.html#/popup"},"options_page": "index.html#/options"
}
复制代码
而背景页面(事件页面)和内容脚本都是无页面的,只需要脚本,所以我使用 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 格式化的扩展程序相关推荐
- 对chrome中出现已尝试对扩展程序降级的问题的一点尝试
今天碰到这个问题,是IDM扩展程序无法在chrome中添加,出现"已尝试对扩展程序降级".百度了一下,网上所说的方法:http://tieba.baidu.com/p/202053 ...
- 如何在Chrome工具栏中固定和取消固定扩展程序
Not all extensions are made equal. Some extensions, like Grammarly, work quietly in the background a ...
- 详细!来看吧,包你不后悔 亲测7个!chrome浏览器好用的应用扩展程序/插件推荐
亲测chrome浏览器好用的应用扩展程序/插件推荐 在这个秃头的时间,我竟然在写博客.因为我今天第一次用cdsn写了解决爬虫报错的博客之后有点兴奋了,所以我打算把我今天做的有意义的事情再写出一篇来. ...
- chrome添加来自其他网站的扩展程序
chrome添加来自其他网站的扩展程序 原文网址:http://support.google.com/chrome_webstore/bin/answer.py?hl=zh-Hans&answ ...
- chrome扩展程序安装_如何从Chrome网上应用店外部安装扩展程序
chrome扩展程序安装 Try to install an extension from outside the Chrome Web Store and Chrome will tell you ...
- Chrome插件安装失败,此扩展程序可能已损坏。
文章目录 问题描述 解决方案 实用插件 油猴脚本 参考文献 问题描述 新版Chrome装插件常常出现问题--Chrome插件安装失败,此扩展程序可能已损坏. 解决方案 打开 Chrome 所在位置,默 ...
- c语言 编译 flash,DSP-C2000 flash编程,自己定义的烧写函数在主函数中运行无法通过...
2018-11-23 14:47:04 评论 提交评论 您好, 的确,Flash API 函数的调用必须在 RAM 中执行.对于 Flash API 函数具体的调用方法,可以参考 ControlSUI ...
- 怎么在Chrome浏览器安装chrome应用商店外的第三方扩展程序?
转载自品略图书馆 http://www.pinlue.com/article/2020/03/2813/0310060784512.html 近日 Google 的 Chrome 浏览器宣布从最新的 ...
- Java之Chrome中运行Applet应用
##简述 由于对安全级别的设置,Java 8中对本地Applet应用程序的运行有安全要求.在Chrome浏览器中运行Applet应用的.html文件,因为受到Java因安全问题的阻止而无法运行.需要对 ...
最新文章
- ReactNative项目打包(Android IOS)
- 前端那些年--npm
- C++学习之路 | PTA乙级—— 1076 Wifi密码 (15 分)(精简)
- 默认文献工具_工具分享??超好用的SCI外文文献下载工具
- 对Linux网络配置管理的简单使用经验
- donet 微服务开发 学习-consul 消费端开发
- FAT文件系统详解(二)
- 基于C/C++的PCM编码与解码简单实现
- 基于51单片机步进电机控制
- WinRAR 密码 模板的秘密:
- 用esp8266做一个网络时钟
- Linux7下Mysql5.7搭建MHA(0.58版本)
- python统计套利_清华编程高手尹成带你基于算法实践python量化交易
- 缓冲区溢出攻击指什么?如何防御?
- Python 进程间的通信
- 英语语音篇 - 特殊发音记录
- JavaScript网页--跨年倒计时
- 2015英国女王殿下的圣诞致辞
- BUC算法及其Python实现
- 【建议收藏】17个XML布局小技巧
热门文章
- 【废弃】【WIP】JavaScript 函数
- Handlebars.js 模板引擎
- 金融产品京东金融2015年战略主攻三大方向:股权众筹、农村金融和校园金融...
- (2 sat) hdu 1824
- XML文件的生成与读取
- 构造函数和析构函数的简单说明
- Win32 窗口篇(1)
- c语言中自守数函数,【C语言训练】自守数问题 (C语言代码)
- hdu4864 贪心
- 【iOS 开发】Objective - C 面向对象 - 方法 | 成员变量 | 隐藏封装 | KVC | KVO | 初始化 | 多态