当前位置: 首页 > 知识库问答 >
问题:

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

杜哲彦
2024-07-04
// .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),
  },
};

共有1个答案

涂泰平
2024-07-04

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 选项来运行一个自定义的脚本,该脚本首先使用你的一个插件处理代码,然后再使用另一个插件处理代码。但是,这种方法可能会比较复杂,并且可能不是最优的解决方案。

 类似资料:
  • 本文向大家介绍如果已经有三个promise,A、B和C,想串行执行,该怎么写?相关面试题,主要包含被问及如果已经有三个promise,A、B和C,想串行执行,该怎么写?时的应答技巧和注意事项,需要的朋友参考一下 参考回答:

  • 我想做一个跟https://geojson.io/一样的可交互的地球,而且还不卡,请问应该用什么方案实现?

  • 当我转到<代码>/银行/1我看到了预期的账户信息。很好,很好。 当我转到<代码>/银行/1/description我看到了描述(好),但我也看到了帐户信息(不好)。 我习惯了Spring的,如果多个路径匹配,事情就会中断——但即便如此,AFAIK,在我的代码中,无论如何只有一个应该匹配? 银行。Java语言 帐户ction.java 日志输出:

  • 问题内容: 最近升级到Spark 2.0,尝试从JSON字符串创建简单的数据集时遇到一些奇怪的行为。这是一个简单的测试用例: 并输出: 即使我仅执行一项操作,“ map”功能似乎仍被执行两次。我以为Spark会懒惰地建立一个执行计划,然后在需要时执行它,但这似乎使得为了将数据读取为JSON并对其进行任何处理,该计划必须至少执行两次。 在这种简单的情况下,这并不重要,但是当map函数长时间运行时,这

  • google protobuf允许我编写如下原型代码: 它可以编译,没问题。我不太明白,对于“可选”字段,当没有指定值时,解码流返回给我默认值,没关系。但是“必需”字段呢,它不能是空的,那么它的“默认”是如何有效的呢?在什么情况下?

  • 我试图在ubuntu服务器上安装npm和nodejs,但注意到不知何故,在运行后,我最终得到了两个版本。我知道这一点,因为当我运行时,它会返回,而当我运行时,它返回。在我继续之前,我想把这个设置好。有人明白我为什么会有两个版本吗?我的理解是,安装nodejs也应该安装npm,但这只允许我以更高的权限运行npm,我知道我不应该这样做。谁能让我知道我做错了什么?谢谢你。