You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
module.exports={rules: {"my-rules": {create: function(context){// rule implementation ...}}},env: {jquery: {globals: {$: false}}},configs: {myConfig: {parser: require.resolve('vue-eslint-parser'),parserOptions: {ecmaVersion: 2018,sourceType: 'module',ecmaFeatures: {jsx: true}},plugins: ["myPlugin"],env: ["browser"],rules: {"myPlugin/my-rule": "error",}},myOtherConfig: {plugins: ["myPlugin"],env: ["node"],rules: {"myPlugin/my-rule": "off",}}},processors: {'.vue': {// takes text of the file and filenamepreprocess: function(text,filename){// here, you can strip out any non-JS content// and split into multiple strings to lintreturn[string];// return an array of strings to lint},// takes a Message[][] and filenamepostprocess: function(messages,filename){// `messages` argument contains two-dimensional array of Message objects// where each top-level array item contains array of lint messages related// to the text that was returned in array from preprocess() method// you need to return a one-dimensional array of the messages you want to keepreturnmessages[0];},supportsAutofix: true// (optional, defaults to false)}}}
module.exports={processors: {// assign to the file extension you want (.js, .jsx, .html, etc.)".ext": {// takes text of the file and filenamepreprocess: function(text,filename){// here, you can strip out any non-JS content// and split into multiple strings to lintreturn[string];// return an array of strings to lint},// takes a Message[][] and filenamepostprocess: function(messages,filename){// `messages` argument contains two-dimensional array of Message objects// where each top-level array item contains array of lint messages related// to the text that was returned in array from preprocess() method// you need to return a one-dimensional array of the messages you want to keepreturnmessages[0];},supportsAutofix: true// (optional, defaults to false)}}};
// in the file to lint:varfoo=2;// ^ error: Avoid using variables named 'foo'// In your tests:varrule=require("../rules/no-avoid-name")varRuleTester=require("eslint").RuleTestervarruleTester=newRuleTester()ruleTester.run("no-avoid-name",rule,{valid: ["bar","baz"],// right datainvalid: [// error data{code: "foo",errors: [{messageId: "avoidName"}]}]})
对于前端开发者来说,ESLint 是比较常用的代码规范和错误检查工具,ESLint 非常强大不仅提供了大量的常用 rules,还有许多实用的 ESLint 插件可以满足各样需求。但随着项目不断迭代发展,可能会遇到已有 ESLint 插件不能满足现在团队开发的情况。那么这时候,我们就需要自定义 Eslint 开发
ESLint Shareable Config
、ESLint Plugins
。eslint-config-<config-name>
)。eslint-plugin-<plugin-name>
) 。ESLint Shareable Config 开发
可分享的扩展配置(
eslint-config-<config-name>
) 是一个 ESLint 配置对象 npm 包,模块名称以eslint-config-<config-name>
、@<scope>/eslint-config-<config-name>
命名,创建比较简单导出配置规则即可。创建扩展配置
创建扩展配置非常简单,创建一个新的
index.js
文件并 export 一个包含配置的对象即可:使用扩展配置
npm 发布扩展包,引入 ESLint 配置:
Eslint plugin 开发
插件(
eslint-plugin-<plugin-name>
) 是一个命名格式为eslint-plugin-<plugin-name>
的 npm 包,模块名称以eslint-plugin-<plugin-name>
、@<scope>/eslint-plugin-<plugin-name>
命名。Eslint plugin 目录
我们可以利用 yeoman 和 generator-eslint 来构建插件的目录结构进行开发,这里我们选用自定义目录,如下:
插件主入口组成部分
Rules - 插件必须输出一个
rules
对象,包含规则 ID 和对应规则的一个键值对。Environments - 插件可以暴露额外的环境以在 ESLint 中使用。
Processors - 定义插件如何处理校验的文件。
Configs - 可以通过配置指定插件打包、编译方式,还可提供多种风格校验配置。
Rules 创建
在开始编写新规则之前,请阅读官方的 ESLint指南,了解下 ESLint 的特点:
off
、警告warn
error
❌,当然还有正常通过不用给任何提示。我们可以通过使用 astexplorer.net, 去了解 ESLint 如何使用 AST 评估校验代码,astexplorer.net 非常强大,还支持 Vue 模板。
规则组成部分
meta
对象包含规则的元数据type
属性表示规则的类型,这是一个"problem"
,"suggestion"
或"layout"
docs
属性是ESLint的核心规则所必需的描述类信息fixable
属性是"code"
或"whitespace"
,如果规则不可修复,请省略fixable属性schema
指定 options 以便ESLint可以防止无效的 规则配置deprecated
属性指示规则是否已被弃用replacedBy
属性表示在不建议使用的规则的情况下,指定替换规则create
函数返回 ESLint 调用方法对象,通过该方法访问 JavaScript 代码的抽象语法树(由ESTree定义的AST)节点context
对象包含与规则上下文相关的信息属性:
parserOptions
- 插件配置的解析器选项id
- 规则ID。options
- 规则的 配置选项settings
- 配置中的 共享设置parserPath parser
- from配置的名称parserServices
- 包含解析器为规则提供的服务的对象方法:
getAncestors()
- 返回当前遍历的节点的祖先数组,从AST的根部开始,一直到当前节点的直接父级getCwd()
- 将cwd
传递的内容返回给Linter, 为当前工作目录getDeclaredVariables
- 返回给定节点声明的getFilename()
- 返回与源关联的文件名getScope()
- 返回当前遍历的节点的 scope ,用于跟踪对变量的引用getSourceCode()
- 返回一个SourceCode
对象,可以使用该对象来处理传递给ESLint的源markVariableAsUsed(name)
- 在当前作用域中使用给定名称标记变量report(descriptor)
- 报告代码中的问题自定义 Processors
ESLint 插件开发,支持自定义处理器来处理 JavaScript 之外的文件,自定义处理器含有两个过程:
preprocess
和postprocess
。自定义处理器大体结构如下:插件测试
ESLint 提供了
RuleTester
实用工具可以轻松地测试你插件中的规则,在peerDependency
指向 ESLint0.8.0
或之后的版本。实践开发 Vue 模板 Eslint plugin
在开发之前,这里要注意由于 Vue 中的单个文件组件并不是普通的 JavaScript,导致无法使用默认解析器,因此引入了新的解析器 vue-eslint-parser。
开发 vue eslint 规则
这里要注意,涉及到自定义的解析器的,需要使用
context.parserServices
访问该解析器解析的抽象语法树内容。vue-eslint-parser
提供了以下三个处理api 方法:实践开发 TypeScirpt 模板 Eslint plugin
2019 年 1 月,TypeScirpt 官方决定全面采用 ESLint 作为代码检查的工具,并创建了一个新项目 typescript-eslint,提供了 TypeScript 文件的解析器 @typescript-eslint/parser 和相关的配置选项 @typescript-eslint/eslint-plugin 等。之前的两个 lint 解决方案已弃用:
我们在开发 TypeScript Eslint,也有很多生态工具,帮助我们快速上手:
TypeScript ESTree —— 将 TypeScript 源代码转换为 ESTree 兼容形式的解析器。
Utils for ESLint Plugins —— TypeScript + ESLint的实用工具。
https://github.com/typescript-eslint/typescript-eslint/blob/v${version}/packages/eslint-plugin/docs/rules/${name}.md
,)({ name: 'await-thenable', meta: { docs: { description: 'Disallows awaiting a value that is not a Thenable', category: 'Best Practices', recommended: 'error', requiresTypeChecking: true, }, messages: { await: 'Unexpectedawait
of a non-Promise (non-"Thenable") value.', }, schema: [], type: 'problem', }, defaultOptions: [], create(context) { const parserServices = getParserServices(context); const checker = parserServices.program.getTypeChecker(); return { AwaitExpression(node): void { const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); const type = checker.getTypeAtLocation(originalNode.expression); if ( !util.isTypeAnyType(type) && !util.isTypeUnknownType(type) && !tsutils.isThenableType(checker, originalNode.expression, type) ) { context.report({ messageId: 'await', node, }); } }, }; },});module.exports = { configs: { base: { "parser": "@typescript-eslint/parser", "parserOptions": { "sourceType": "module", "allowImportExportEverywhere": false }, plugins: ['@typescript-eslint'], rules: { '@typescript-eslint/adjacent-overload-signatures': 'error', '@typescript-eslint/array-type': 'error', '@typescript-eslint/await-thenable': 'error', } } }, env: { browser: true, es6: true }, rules: { '@typescript-eslint/adjacent-overload-signatures': 'error', '@typescript-eslint/array-type': 'error', '@typescript-eslint/await-thenable': 'error', } }Other Resource扩展eslint-plugin-boilerplate可以通过使用 astexplorer.net,选择
@typescript-eslint/parser
解析器,去了解 ESLint 如何使用 评估校验代码 TypeScript 代码,从而方便我们快速开发 rules。eslint-plugin-boilerplate
eslint-plugin-boilerplate —— 快速开发 eslint plugins 模版样例。
扩展
stylelint 插件开发
Other Resource
ruletester
Eslint
The ESLint Vue Plugin Developer Guide
Working with Rules
开发一个 plugin 插件
Shareable Configs
vue-eslint-parser AST docs
【AST篇】教你如何动手写 Eslint 插件
The text was updated successfully, but these errors were encountered: