Свой плагин за пять минут
Плагин PostCSS — это обычная функция на JavaScript, которая возвращает объект с именем и обработчиками — функциями, которые PostCSS вызывает для узлов дерева: для каждого правила, каждого свойства и так далее. Написать свой плагин проще, чем кажется, и это лучший способ понять, как работают остальные.
Задача
В стилях блога не должно быть !important: он ломает обычный порядок применения правил. Напишем плагин, который убирает !important и предупреждает об этом в терминале.
Код плагина
Создайте папку plugins/ в корне проекта и файл plugins/no-important.js:
// plugins/no-important.js
const noImportant = () => {
return {
postcssPlugin: 'no-important',
Declaration(decl, { result }) {
if (decl.important) {
decl.warn(result, `Убран !important у свойства ${decl.prop}`);
decl.important = false;
}
},
};
};
noImportant.postcss = true;
export default noImportant;Разберём по строкам:
| Строка | Смысл |
|---|---|
postcssPlugin | Имя плагина, видно в сообщениях |
Declaration | Вызывается для каждого объявления вида свойство: значение |
decl.important | true, если у объявления есть !important |
decl.warn | Добавляет предупреждение с номером строки |
noImportant.postcss = true | Метка, по которой PostCSS узнаёт плагин |
Подключение
Импортируйте плагин по относительному пути, как любой модуль:
// postcss.config.js
import postcssPresetEnv from 'postcss-preset-env';
import noImportant from './plugins/no-important.js';
export default {
plugins: [noImportant(), postcssPresetEnv()],
};Проверьте на файле с !important:
/* styles/main.css */
.post-title {
color: #1e293b !important;
margin: 0;
}После npx postcss styles/main.css -o css/main.css в терминале появится предупреждение с позицией — строка 2, столбец 3:
2:3 ⚠ Убран !important у свойства color [no-important]А в css/main.css:
.post-title {
color: #1e293b;
margin: 0;
}Другие обработчики
| Обработчик | Когда вызывается |
|---|---|
Once(root) | Один раз для всего файла |
Rule(rule) | Для каждого правила с селектором, rule.selector |
AtRule(atRule) | Для каждой директивы вроде @media, atRule.name |
Declaration(decl) | Для каждого объявления, decl.prop и decl.value |
Обработчику Declaration можно передать объект с именами свойств — тогда функция будет вызываться только для них, например Declaration: { color: (decl) => ... }.
Частая ошибка
Убрать строку noImportant.postcss = true и подключить плагин без вызова — noImportant вместо noImportant(). Без метки PostCSS считает функцию плагином старого формата, вызывает её с деревом, а возвращённый объект с обработчиками выбрасывает. Ошибки не будет, но и !important останется на месте. Держите метку postcss в файле плагина и вызывайте его в конфигурации со скобками, как остальные плагины.