【问题标题】:Postcss 8 plugin: How to avoid loop into Declaration function?Postcss 8 插件:如何避免循环进入声明函数?
【发布时间】:2020-10-12 22:54:28
【问题描述】:

您好 postcss 专家!

我正在将旧插件更新为 postCSS 8 API,但遇到了一些问题。

这个简单的 postCSS 插件陷入了无限循环:

module.exports = (options = {}) => {
  return {
    postcssPlugin: 'postcss-failing-plugin',
    Declaration(decl) {
      if (decl.prop.startsWith('--')) {
        decl.prop = decl.prop.replace(/^--/, `--prefix-`);
      }
    },
  };
};

module.exports.postcss = true;

文档提到了这种行为:

插件将重新访问您更改或添加的所有节点。如果您要更改任何子级,插件也会重新访问父级。只有OnceOnceExit 不会被再次调用。 writing a plugin

但没有什么可以避免的。

如何编辑Declaration中的值而不造成无限循环?

【问题讨论】:

    标签: postcss


    【解决方案1】:

    您可能会重复为已添加前缀的自定义属性声明添加前缀,导致声明访问者无限运行。

    您可以使用negative lookahead assertion (?!) 来匹配以特定自定义属性前缀开头的自定义属性,即^--(?!prefix-)

    const matcher = /^--(?!prefix-)/
    const replacement = '--prefix-'
    
    const ensure = value => value.replace(matcher, replacement)
    
    // these _should not_ receive a new prefix
    ensure('foo')          // "foo"
    ensure('prefix-foo')   // "prefix-foo"
    ensure('--prefix-foo') // "--prefix-foo"
    
    // these _should_ receive a new prefixed
    ensure('--foo')            // "--prefix-foo"
    ensure('--prefixable-foo') // "--prefix-prefixable-foo"
    

    适用于您的示例

    module.exports = (options = {}) => {
      return {
        postcssPlugin: 'postcss-failing-plugin',
        Declaration(decl) {
          /** Matches a `--` property not beginning with `--prefix-`. */
          const match = /^--(?!prefix-)/
    
          if (match.test(decl.prop)) {
            decl.prop = decl.prop.replace(match, `--prefix-`);
          }
        },
      };
    };
    
    module.exports.postcss = true;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-11
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 2011-03-14
      • 1970-01-01
      相关资源
      最近更新 更多