当前位置: 首页 > 科技观察

写一个Eslint插件:VueTemplate中Class顺序的检查和自动修复

时间:2023-03-13 05:02:56 科技观察

有朋友问我如何固定vuetemplate中类名顺序、属性名顺序、options中属性顺序,使用eslint可以做到吗。答案是肯定的,但是需要自己写eslint插件来检查修复。考虑到他可能没有写过eslint插件,我先提取了比较简单的类名检查修复类顺序的插件实现了。思路分析一、eslint可以解析vue模板吗?可以,因为eslint的解析器支持切换,而vue实现了相应的解析器,所以在eslint中可以使用vue-eslint-parser来解析模板。我们可以使用astexplorer.net查看parse生成的AST。我们要处理的是class属性,即VAttribute的value部分可以支持传入一个comparator来自定义顺序,排序后设置回去。当然vue的模板是支持{}引用数据的,我们不处理,可以过滤掉。思路比较简单,下面来写代码实现一下。对于代码实现,我们可以将插件命名为vue-class-order。首先我们引入eslint,将useEslintrc设置为false,即不使用配置文件,然后在overrideConfig属性中设置各种配置,在rules中填写这个plugin。const{ESLint}=require("eslint");constengine=newESLint({fix:false,overrideConfig:{parser:'vue-eslint-parser',parserOptions:{sourceType:'module'},rules:{"vue-类顺序":["error"]}},rulePaths:['./'],useEslintrc:false});这里的解析器需要用到vue-eslint-parser,rulePaths也是找到规则的路径,要设置下。fix设置为false意味着没有自动修复。之后,调用其lintText方法对代码进行lint。(asyncfunctionmain(){constresults=awaitengine.lintText(``);console.log(results[0].output);constformatter=awaitengine.loadFormatter("stylish");constresultText=formatter.format(results);console.log(结果文本);})();然后在插件中取出:module.exports={meta:{fixable:true},create(context){constcomparator=context.options[0];}};这里的比较器来自从上下文中检索到的参数。插件的结构是meta,create两部分,meta是描述插件本身的各种元信息,create部分是插件的主要逻辑。创建部分返回一个访问者,声明要在哪个节点上执行什么操作。但是因为我们使用的解析器是vue自定义的(vue-eslint-parser),所以这里的访问者也应该使用它提供的,即:module.exports={meta:{fixable:true},create(context){constcomparator=context.options[0];returncontext.parserServices.defineTemplateBodyVisitor({"VAttribute[key.name=class]"(node){}});}};在context.parserServices.defineTemplateBodyVisitor方法中传入具体的visitor,比如我们需要处理VAttribute节点。eslint支持esqury的写法,即可以通过选择器的方式指定要处理的节点。这里我们指定key.name作为类的VAttribute节点,获取该节点的值,排序,看是否正确。不对就报错。"VAttribute[key.name=class]"(node){constclassStr=node.value.value;if(!classStr.includes('{')){//过滤出classconstcurOrder=classStr.split(/\s/);constshouldOrder=[...curOrder].sort(比较器);if(curOrder.some((item,index)=>curOrder[index]!==shouldOrder[index])){context.report({node,message:'className的顺序错误:'+classStr,loc:node.value.loc});}}}这样我们就实现了vue模板中类顺序的lint。试试效果吧:我们实现了className顺序的lint!当然只报错不修复就更流氓了,还得实现自动修复。修复是替换value部分,即获取value的范围(起止下标),将范围内的文本替换成fixerapi。(这里要考虑引用)context.report({node,message:'className的顺序错误:'+classStr,loc:node.value.loc,*fix(fixer){const[start,end]=node.value.range;yieldfixer.replaceTextRange([start+1,end-1],shouldOrder.join(''))}});我们将fixer设置为true,再次运行:自动修复完成,没有报错!我们实现它检查并自动修复vue模板中类的顺序!总结Eslint可以基于AST对代码格式进行检查和修复。基于AST,必然有相应的解析器。eslint支持parser的扩展,所以eslint的解析器有很多。如果要解析vue模板,可以使用vue-eslint-parser。可以使用astexplorer.net直观地查看它。我们想检查vue模板中类的顺序。经过分析,我们需要取出key为class的VAttribute节点的值,然后根据传入的比较器进行排序。如果顺序不一致,就会报错。并且还可以通过fixerAPI自动修复,即替换范围内的文本。这里我们通过api调用eslint,通过cli也是一样。本文实现了一个比较简单的eslint插件,检查修复了vue模板中的代码格式,希望能帮助大家理清eslint插件的开发思路。