prettier 写了两个 plugin ,为什么只有最后一个生效?如果我想两个都执行应该怎么修改?

// .prettierrc.js
const prettierPluginSelfClosingTags = require('./.prettier-plugins/prettier-plugin-self-closing-tags.js');
const prettierPluginTransformImports = require('./.prettier-plugins/prettier-plugin-transform-imports.js');
// prettier-plugin-organize-imports
module.exports = {
  singleQuote: true,
  plugins: [
    // 这个是用于将相对路径变为绝对路径的
    prettierPluginTransformImports,
    // 这个是用于将标签变为自闭合标签的
    prettierPluginSelfClosingTags,
  ],
};

内部逻辑和 https://github.com/simonhaenisch/prettier-plugin-organize-imports/blob/master/index.js 是一样的,都是增加了 withPluginsPreprocess 然后在 preprocess 做的处理

// prettier-plugin-self-closing-tags
// @ts-expect-error
const { parsers: babelParsers } = require('prettier/parser-babel');
// @ts-expect-error
const { parsers: typescriptParsers } = require('prettier/parser-typescript');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const generate = require('@babel/generator').default;
function selfClosingTagsPreprocessor(code, options) {
  const ast = parser.parse(code, {
    plugins: ['typescript', 'jsx'],
    sourceType: 'module',
  });
  traverse(ast, {
    JSXElement(path) {
      const node = path.node;
      // 如果 children 不存在,变为自闭合标签
      if (node.children.length === 0) {
        node.closingElement = null;
        node.openingElement.selfClosing = true;
      }
    },
  });
  return generate(ast, {
    retainLines: true,
    // compact: false,
  }).code;
}
const withPluginsPreprocess = (parser) => {
  return {
    ...parser,
    /**
     * @param {string} code
     * @param {import('prettier').ParserOptions} options
     */
    preprocess: (code, options) =>
      selfClosingTagsPreprocessor(
        parser.preprocess ? parser.preprocess(code, options) : code,
        options
      ),
  };
};
module.exports = {
  parsers: {
    babel: withPluginsPreprocess(babelParsers.babel),
    'babel-ts': withPluginsPreprocess(babelParsers['babel-ts']),
    typescript: withPluginsPreprocess(typescriptParsers.typescript),
  },
};
阅读 850
avatarAI BotBETA

Prettier 插件系统的工作原理是,当你为特定的解析器(parser)注册了插件时,这些插件的 preprocess 函数会在 Prettier 的格式化过程开始之前被调用。在你的例子中,你创建了两个插件:prettierPluginSelfClosingTagsprettierPluginTransformImports,并尝试将它们都注册到 Prettier 的配置中。

然而,由于你为每个解析器(babel、babel-ts、typescript)都返回了一个新的带有 preprocess 函数的解析器对象,并且每个新的解析器对象只包含了一个 preprocess 函数,因此,当 Prettier 使用这些解析器时,只会执行最后一个被注册的插件的 preprocess 函数

为了解决这个问题,并让你的两个插件都能正常工作,你需要确保每个插件的 preprocess 函数都能执行其自己的逻辑,并且如果需要,还能调用之前注册的插件的 preprocess 函数。这通常可以通过将插件的 preprocess 函数封装到一个链式调用中来实现。

但是,Prettier 插件 API 并没有直接支持这种链式调用。因此,你需要手动管理这种链式调用,或者重新设计你的插件,以便它们能够协同工作,而不是相互替代。

一个可能的解决方案是,在你的插件中创建一个中央化的 preprocess 函数,该函数调用你所有插件的 preprocess 函数。但是,这需要你能够修改这些插件的代码,以便它们可以被这样调用。

另一种可能的解决方案是,只使用一个插件,并在该插件的 preprocess 函数中同时包含两个插件的逻辑。这样,你就可以确保两个插件的逻辑都会被执行。

如果你不能修改插件的代码,或者不想使用一个插件来包含两个插件的逻辑,那么你可能需要寻找其他方法来达到你想要的效果,比如使用 Prettier 的 --with-node-script 选项来运行一个自定义的脚本,该脚本首先使用你的一个插件处理代码,然后再使用另一个插件处理代码。但是,这种方法可能会比较复杂,并且可能不是最优的解决方案。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏