我正在使用Jscodeshift编写我的第一个codemod。 我当前的目标是导出分配了特定标识符的const。
因此,如果我定位每个名为stuff
的变量,则在脚本运行后将对其进行命名-导出。
IN:
const stuff = 4;
OUT:
export const stuff = 4;
这是我所拥有的精简版本。它可以正常工作,但看起来很脆,并且有很多缺点。
const constName = "stuff";
module.exports = (fileInfo, api) => {
const j = api.jscodeshift;
const root = j(fileInfo.source);
const declaration = root.find(j.VariableDeclaration, {
declarations: [
{
id: {
type: "Identifier",
name: constName
}
}
]
});
declaration.forEach(n => {
n.insertBefore("export");
});
return root.toSource();
};
这将导致(注意不需要的新行)
export
const stuff = 4;
如果将此源提供给脚本,这也将严重失败。
IN:
// hey
const stuff = 4;
OUT:
export
// hey
const stuff = 4;
我非常确信n.insertBefore("export");
确实是这里的罪魁祸首,我想使用jscodeshift构建器自己构建命名的导出文件,但实际上无法使其工作。
这里有什么建议吗?
答案 0 :(得分:1)
.insertBefore
不是正确的使用方法。这是为了在另一个节点之前插入整个新节点。
如何用VariableDeclaration
替换 ExportNamedDeclaration
。如果查看export const stuff = 4;
的AST,您会发现它具有属性declaration
,其值为VariableDeclaration
节点。这使我们的转换变得容易了:找到VariableDeclaration
,创建一个新的ExportNamedDeclaration
,将其declaration
属性设置为找到的节点,然后用新节点替换找到的节点。
要了解如何构建节点,我们可以查看ast-type
's ast definitions。
const constName = "stuff";
module.exports = (fileInfo, api) => {
const j = api.jscodeshift;
return j(fileInfo.source)
.find(j.VariableDeclaration, {
declarations: [
{
id: {
type: "Identifier",
name: constName
}
}
]
})
.replaceWith(p => j.exportDeclaration(false, p.node))
.toSource();
};