Может ли PostCSS изменять содержимое CSS перед другим плагином?

#postcss

#postcss

Вопрос:

Допустим, у вас есть плагин PostCSS, который анализирует подобные at-правила, @remove а затем удаляет их. Вот пример программы:

 const fs = require('fs');
const postcss = require('postcss');
const plugin = func => {
  func.postcss = true;
  return func;
};

fs.readFile('test.css', (err, css) => {
  postcss([
    plugin(() => ({
      postcssPlugin: 'postcss-remove',
      Root(root) {
        console.log('---BEFORE postcss-remove---')
        console.log(root.source.input.css);
        root.walkAtRules('remove', atRule => {
          atRule.remove();
        });
        console.log('---AFTER postcss-remove---')
        console.log(root.source.input.css);
      }
    })),
    plugin(() => ({
      postcssPlugin: 'postcss-another',
      Root(root) {
        console.log('---BEFORE postcss-another---')
        console.log(root.source.input.css);
        console.log('---AFTER postcss-another---')
      }
    }))
  ]).process(css).then(result => {
    console.log(result.css);
  })
});
 

Это test.css файл:

 @remove 'foo.js';

.foo {
  color: red;
}
 

И это вывод:

 ---BEFORE postcss-remove---
@remove 'foo.js';

.foo {
  color: red;
}

---AFTER postcss-remove---
@remove 'foo.js';

.foo {
  color: red;
}

---BEFORE postcss-another---
@remove 'foo.js';

.foo {
  color: red;
}

---AFTER postcss-another---
.foo {
  color: red;
}
 

Как вы можете видеть из выходных данных, postcss-другой все еще видит @remove правила. Удален только вывод CSS @remove . Следующий плагин в цепочке @remove вообще не должен отображаться. Я думал, что это поведение по умолчанию, но это не так.

Есть ли способ полностью обработать @remove ПЕРЕД любым другим плагином?

Ответ №1:

Как следует из названия, .source.input.css свойство CSS nodes содержит код CSS, который изначально был передан в PostCSS, а не состояние таблицы стилей, как было изменено впоследствии. Он существует в основном для того, чтобы иметь возможность использовать смещения, которые указывают на расположение правил в исходном вводе:

 root.walkAtRules('remove', atRule => {
  const src = atRule.source;
  atRule.remove();
  console.info('removed this rule: ', src.input.css.substr(src.start.offset, src.end.offset));
});
 

Данные таблицы стилей передаются между плагинами не в виде исходного кода, а в виде синтаксического дерева, поскольку это то, с чем работают плагины в любом случае.

Если вы хотите получить исходный код, который отражает текущее состояние таблицы стилей, все, что вам нужно сделать, это преобразовать интересующий вас синтаксический узел в строку:

 module.exports = () => {
  return {
    postcssPlugin: 'postcss-another',
    Root(root) {
      console.log('---BEFORE postcss-another---')
      console.log(root.toString());
      console.log('---AFTER postcss-another---')
    }
  }
};

module.exports.postcss = true;