开发一个 vue 的 eslint 插件

691 阅读2分钟

需求

vue template里面的事件名只能已on 开头

实现效果

image-20230528172725188

实现步骤

创建调试程序和 eslint 插件程序

创建调试程序

我创建的文件夹名称为eslint-demo

pnpm create vue

创建eslint 插件程序

我创建的文件夹名称为v-on-name-sartwith-on

首先安装eslint 脚手架

pnpm i -g yo
pnpm i -g generator-eslint
​

生成 Eslint 插件工程。

 yo eslint:plugin

为插件创建一条规则,执行如下命令:

yo eslint:rule

文件目录参考

image-20230528173706552

link 插件

v-on-name-sartwith-on 这个项目里面执行

pnpm link --global

eslint-demo 这个项目里面执行(注意, 这里的名称是package.json 里面的名称)

pnpm link --global eslint-plugin-v-on-handler-name-style
​

编写代码

eslint-demo项目 App.vue

<script setup>
const handler = () => {
  console.log('123')
}
</script><template>
  <p @click="handler" class="a"></p>
</template>

v-on-name-sartwith-on 项目

lib/index.js

/**
 * @fileoverview 判断 v-on 的 handler 是否已 on 开头
 * @author abigmiu
 */
'use strict';
​
// const vueParser = require.resolve('vue-eslint-parser');//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------const requireIndex = require('requireindex');
​
//------------------------------------------------------------------------------
// Plugin Definition
//------------------------------------------------------------------------------const rules = requireIndex(__dirname + '/rules');
module.exports = {
    configs: {
        recommended: {
            plugins: ['v-on-handler-name-style'],
            rules: {
                'v-on-handler-name-style/v-on-handler-name-style': ['error'],
            },
        },
    },
    parser: require.resolve('vue-eslint-parser'), // 这里可能要安装vue-eslint-parser
    env: {
        browser: true,
        es6: true,
    },
    rules: rules,
};
​

lib/rules/v-on-handler-name-style.js

/**
 * @fileoverview 判断 v-on 的 handler 是否已 on 开头
 * @author abigmiu
 */
'use strict';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
    meta: {
        type: 'suggestion',
        docs: {
            description: '判断 v-on 的 handler 规则',
        },
        fixable: 'code', // Or `code` or `whitespace`
        schema: [],
        messages: {
            error: '事件名不已 on 开头',
        },
    },
​
    create(context) {
        // variables should be defined here
​
        //----------------------------------------------------------------------
        // Helpers
        //----------------------------------------------------------------------
​
        // any helper functions should go here or else delete this section
​
        //----------------------------------------------------------------------
        // Public
        //----------------------------------------------------------------------
        return context.parserServices.defineTemplateBodyVisitor({
            "VAttribute[directive=true][key.name.name='on'][key.argument!=null]"(
                node
            ) {
                const value = node.value;
                if (value.type === 'VExpressionContainer') {
                    const expression = value.expression;
                    const reg = /^on[A-Z]/;
                    if (!reg.test(expression.name)) {
                        context.report({
                            node,
                            messageId: 'error',
                            loc: value.loc,
                        });
                    }
                }
            },
            // visitor functions for different types of nodes
        });
    },
};
​

为什么需要context.parserServices.defineTemplateBodyVisitor

vue-eslint-parser 提供了以下三个处理api 方法:

// 处理 template 语法树遍历方法
// Define handlers to traverse the template body  
context.parserServices.defineTemplateBodyVisitor()
// 获取缓存的 template 语法树结构
context.parserServices.getTemplateBodyTokenStore()
// 获取根结点 document fragment.
context.parserServices.getDocumentFragment()

VAttributedirective=true[key.argument!=null] 这个选择器怎么确定的

AST explorer 用这个网站, 注意红框位置, 要选择对应的选择器 才能选择

image-20230528174142371

参考链接

手把手教你实现一个自定义 eslint 规则 - 掘金 (juejin.cn)

写一个 eslint 插件:vue template 中 class 顺序的检查和自动修复 - 掘金 (juejin.cn)

自定义 Eslint 开发 · Issue #70 · pfan123/Articles (github.com)