为了解决路径问题,我写了一个eslint plugin

前言

公司的老项目部分import是用的相对路径,之前写需求的时候也改过一部分,但是文件太多了,一个一个改显然不是长久之计,昨天突发奇想能不能用eslint --fix来做下自动修复呢?于是,花了大概一个多小时写了一个plugin来满足需求。

效果

昨天下午我写完之后,晚上回家在github上,找到了一个库github.com/steelsojka/...

这个库也能实现相同的效果,而且做的挺完善,不足之处在于不支持动态引入,比如这种

js 复制代码
import('../../test.js')

作者也不维护了,于是我就自己补了一下处理动态引入的逻辑。

效果图如下:

思路

获取处理文件的路径

要想实现相对路径的修改,首先要拿到处理文件的绝对路径,这个我们可以 context.getFilename() 或者 context.filename() 获取

它的值类似于 /Users/chouchouji/alias-manager/src/aliases.ts

处理相对路径

然后就是获取 from 后面或者 import 里面的相对路径,eslint 是通过 ast 来实现代码内容解析的,我们要处理两种形式的 import

转化相对路径为绝对路径

这个就比较简单了,可以借助 node:path 来处理。

先通过 path.dirname 获取当前文件的上一级目录,通过 path.resolve 获取引入文件的绝对路径,然后根据需求出路路径,如果想把 src 替换为 @,就切割获取绝对路径 src 后面的内容,用 replace 方法做替换就行

实践

可以通过 --rulesdir 这个参数来实现本地调试,

rules 是我新创建的目录,下面有我写的 eslint rule 的代码,

然后在你的 eslint 配置文件中加下该 rule

package.json 中加一个命令

js 复制代码
"test:lint": "eslint --rulesdir ./rules \"src/**/*.{js,vue}\" --fix"

最后控制台执行 pnpm test:lint 就可以了

源码

js 复制代码
## use-alias.js

const path = require('path');

module.exports = {
  meta: {
    name: 'eslint-plugin-alias',
    type: 'problem',
    docs: {
      description: 'Use Alias',
    },
    messages: {
      error: 'Use Alias',
    },
    fixable: 'code',
  },
  create: function (context) {
    const filename = context.getFilename();
    return {
      ImportDeclaration(node) {
        if (node.source.value.startsWith('.')) {
          context.report({
            node,
            messageId: 'error',
            fix: function (fixer) {
              const absolutePath = path.resolve(
                path.dirname(filename),
                node.source.value,
              );
              const relativePath = 'src' + absolutePath.split('/src')[1];
              return fixer.replaceText(
                node.source,
                `'${relativePath.replace('src', '@')}'`,
              );
            },
          });
        }
      },
      ImportExpression(node) {
        if (node.source.value.startsWith('.')) {
          context.report({
            node,
            messageId: 'error',
            fix: function (fixer) {
              const absolutePath = path.resolve(
                path.dirname(filename),
                node.source.value,
              );
              const relativePath = 'src' + absolutePath.split('/src')[1];
              return fixer.replaceText(
                node.source,
                `'${relativePath.replace('src', '@')}'`,
              );
            },
          });
        }
      },
    };
  },
};

结尾

如有疑问,欢迎留言

相关推荐
zyplayer-doc2 小时前
VuePress类静态文档站和动态知识库怎么选:两种技术路线的适用场景
javascript·人工智能·后端·安全·智能手机
紫禁玄科3 小时前
Shai-Hulud:npm生态的自我复制蠕虫风暴
前端·npm·node.js
东风破_3 小时前
后端API没写好,前端难道干等着吗?
前端
用户938515635073 小时前
从前后端分离到前端接口工程:React + MockJS + Vite 解析
前端·后端·全栈
用户938515635074 小时前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformers.js 全链路实战(三)
前端·react.js·typescript
excel4 小时前
当前端行情变差,我们为什么还要坚持?
前端
鸿是江边鸟,曾是心上人4 小时前
快速搭建HTTPS本地开发环境
前端
To_OC5 小时前
写了 5 个表单 Demo 后,我终于彻底搞懂了 React 受控与非受控组件
前端·react.js·前端框架
Sterting5 小时前
第9课 Vue Router 路由
前端·vue.js
用户059540174465 小时前
LangChain Memory 测试踩坑实录:用 pytest 自动化回归对话记忆,我折腾了整整一个周末
前端·css