用 TS + Vue 写了一个在 Chrome 中运行 Prettier 格式化的扩展程序

im, 无色
im, 无色
im, 无色
884
文章
0
评论
2019年7月4日10:44:54 评论 709

用 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 的所有功能:

用 TS + Vue 写了一个在 Chrome 中运行 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...

这里我想让大家注意一点,就是 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_js

node_js: 9

install:
  - yarn

script:
  - yarn lint
  - yarn lint:prettier

cache:
  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 扩展了!
先给大家放一张动态图,相信看完之后大家就知道是干嘛用的了!

用 TS + Vue 写了一个在 Chrome 中运行 Prettier 格式化的扩展程序

没错!这是一款可以让 Prettier 运行在 Chrome 的扩展程序!
它主要用来在线写 markdown 时格式化,适用于:

  • sf.gg 答题
  • gayhub 提 issues、pr
  • 在线写博客
  • 等等...

主要功能:

  • 中英文之间自动添加空格
  • 自动对齐表格
  • 自动对齐列表
  • 代码块指定的语言如果支持的话会使用对应的 parser 格式化
  • 等等...

用法非常简单,你只需要在 markdown 编辑器获得焦点的时候按下 ALT + F 快捷键即可格式化!

可以配置 Prettier 中的所有选项

用 TS + Vue 写了一个在 Chrome 中运行 Prettier 格式化的扩展程序

这个扩展是基于昨天发布的 Prettier v1.13.0 版本进行开发的,这个项目我已经蓄谋已久了,无奈之前版本的 Prettier 并不支持在浏览器中运行,所以我一直在关注 Prettier 的动态,终于在昨天 v1.13.0 发布,并支持在浏览器中运行!于是老夫我撸起袖子就是一顿干,然后申请把项目添加到 Prettier 官网中,并得到了官方人员的认可!

用 TS + Vue 写了一个在 Chrome 中运行 Prettier 格式化的扩展程序

官方还转推了 (๑>◡<๑)

用 TS + Vue 写了一个在 Chrome 中运行 Prettier 格式化的扩展程序

我绝对没有膨胀,我没有!(留下了没有技术的泪水,逃
顺便问一句,大家有没有觉得我这篇文章的排版特别舒服呀?这都是 Prettier 的功劳哟(

扩展的原理非常简单,popup 页面用来修改 Prettier 的各种选项并保存到 localStorage 中。
在背景页面(事件页面)注册右键菜单和快捷键命令,通过 chrome.tabs.sendMessage 与内容脚本通信。
在内容脚本通过 chrome.runtime.onMessage 监听消息,如果收到了格式化指令则获取当前获得焦点的元素判断是否是一个多行文本框,如果是并且内容不为空则调用 prettier.format 方法将当前元素的内容和插件还有 localStorage 中保存的选项传递给它,获得格式化的结果后重新赋值文本框。

源码在这里:https://github.com/u3u/pretti...
官方人员已 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-...

参考文档: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-...

通过配置 vue.config.js 删除 split-manifest 和 inline-manifest 即可。

module.exports = {
  chainWebpack: (config) => {
    config.plugins.delete('split-manifest').delete('inline-manifest');
  },
};

参考文档:https://crxdoc-zh.appspot.com...

如何开发一个 Chrome 扩展?

概述:https://crxdoc-zh.appspot.com...
清单文件格式:https://crxdoc-zh.appspot.com...
JavaScript API:https://crxdoc-zh.appspot.com...

im, 无色
  • 本文由 发表于 2019年7月4日10:44:54
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: