postcss - PostCSS 自定义插件 - TypeError:无法读取未定义的属性“_autoprefixerPrefix”
问题描述
我正在开发一个 postCSS 插件,您可以在其中将自定义 atRules 用于 bem 类。这是演示: https ://astexplorer.net/#/gist/147ddf920699ac24b690a05f8f8da8f1/15aeb3c85224f3d20de47a1774c25f330ed9d16e
它本身可以正常工作,但是在项目中与 autoprefixer 一起使用时,autoprefixer 会报错:TypeError: Cannot read property '_autoprefixerPrefix' of undefined
.
您能想到的任何原因或任何调试方法可能吗?
您还可以将下面的所有代码复制粘贴到 npm runkit 中以获取确切的错误。
const autoprefixer = require("autoprefixer");
const postcss = require('postcss');
const css = `
@b BaseButton {
@apply shadow-neon-default;
@apply rounded-full;
box: horizontal;
position: relative;
overflow: hidden;
user-select: none;
&:hover {
@apply shadow-neon-less;
}
&:active {
@apply shadow-neon-inset;
}
@is faded {
opacity: 0.8;
}
}
`;
const toTitleCase = (str) => {
return str.replace(/\w\S*/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
};
const createRule = (selector, { source, nodes, raws }) => {
return postcss.rule({
selector,
source,
nodes,
raws
});
};
const recycleBin = {
element: [],
modifier: [],
is: [],
when: [],
whenIs: []
};
const emptyRecycleBin = (type) => {
recycleBin[type].forEach((rule) => {
rule.remove();
});
};
const willInsert = [];
const insertEverything = (root) => {
Object.values(willInsert).forEach((insertInstruction) => {
insertInstruction.rules.reverse().forEach((rule) => {
root.insertAfter(insertInstruction.baseRule, rule);
});
insertInstruction.baseRule.remove();
});
};
let newBlock = null;
const processBlocks = (container, next) => {
container.walkAtRules(/^block$|^b$/gi, (blockAtRule) => {
willInsert[`.${blockAtRule.params}`] = {
baseRule: blockAtRule,
rules: []
};
newBlock = createRule(`.${blockAtRule.params}`, blockAtRule);
willInsert[`.${blockAtRule.params}`].rules.push(newBlock);
next(newBlock);
});
};
const processElements = (container, blockName, next) => {
container.walkAtRules(/^element$|^e$/gi, (elementAtRule) => {
const newElement = createRule(`${container.selector}__${elementAtRule.params}`, elementAtRule);
willInsert[blockName].rules.push(newElement);
recycleBin.element.push(elementAtRule);
next(newElement);
});
emptyRecycleBin('element');
};
const processModifier = (container, blockName) => {
container.walkAtRules(/^modifier$|^m$/gi, (modifierAtRule) => {
const newModifier = createRule(`${container.selector}--${modifierAtRule.params}`, modifierAtRule);
willInsert[blockName].rules.push(newModifier);
recycleBin.modifier.push(modifierAtRule);
});
emptyRecycleBin('modifier');
};
const processIs = (container, blockName) => {
container.walkAtRules('is', (isAtRule) => {
if (isAtRule.parent.name !== 'when') {
const newModifier = createRule(`${container.selector}--is${toTitleCase(isAtRule.params)}`, isAtRule);
willInsert[blockName].rules.push(newModifier);
recycleBin.is.push(isAtRule);
}
});
emptyRecycleBin('is');
};
const processWhen = (container, blockName, cb) => {
container.walkAtRules('when', (whenAtRule) => {
const newWhen = createRule(`[class*='${container.selector.substring(1)}--${whenAtRule.params}']`, whenAtRule);
willInsert[blockName].rules.push(newWhen);
newWhen.walkAtRules('is', (isAtRule) => {
const newIs = createRule(`${newWhen.selector.slice(0, -2)}:${isAtRule.params}']`, isAtRule);
willInsert[blockName].rules.push(newIs);
recycleBin.whenIs.push(isAtRule);
});
emptyRecycleBin('whenIs');
recycleBin.when.push(whenAtRule);
});
emptyRecycleBin('when');
};
const process = (root) => {
processBlocks(root, (processedBlock) => {
processElements(processedBlock, processedBlock.selector, (processedElement) => {
processModifier(processedElement, processedBlock.selector);
processIs(processedElement, processedBlock.selector);
processWhen(processedElement, processedBlock.selector);
});
processModifier(processedBlock, processedBlock.selector);
processIs(processedBlock, processedBlock.selector);
processWhen(processedBlock, processedBlock.selector);
insertEverything(root);
});
};
const bemmify = postcss.plugin('postcss-bem', (options = {}) => {
return (root) => {
process(root);
};
});
postcss([ bemmify, autoprefixer ]).process(css).then(result => {
result.warnings().forEach(warn => {
console.warn(warn.toString())
})
console.log(result.css)
});
解决方案
推荐阅读
- rust - Rust 生命周期的问题:impl 使用匿名生命周期,函数使用 <'a>,更改生命周期以匹配会导致错误
- python - 使用 python matplotlib 绘制条形图,在同一条形图中有两个不同的数据
- python - Python 播放 ffpyplayer 后删除文件
- ios - 将从 SOAP 服务返回的数据传递到自定义对象数组
- python - 如何让机器人使用命令发送随机在线图片和报价?
- npm - NUXT npm run build on nuxt events.js:292 throw er; // 未处理的“错误”事件 ^
- apache - 如果是文档,则最后一个路径名重定向到第一个路径名
- python - 如何并行化 Databricks 文件复制/上传操作?
- django - Neovim for Django:元类无法识别
- firebase - Firebase:在验证时禁用帐户或在启用后发送验证