babel-plugin-r-sugar
Version:
A Babel plugin that adds Vue-style v-if directive support to React
90 lines (84 loc) • 4.1 kB
JavaScript
;
function vIfPlugin(path, t) {
var _a, _b;
// 安全检查
if (!((_b = (_a = path.node) === null || _a === void 0 ? void 0 : _a.openingElement) === null || _b === void 0 ? void 0 : _b.attributes))
return;
const vIfAttribute = path.node.openingElement.attributes.find((attr) => attr.type === "JSXAttribute" && attr.name.name === "v-if");
if (!vIfAttribute || !vIfAttribute.value || vIfAttribute.value.type !== 'JSXExpressionContainer')
return;
path.node.openingElement.attributes = path.node.openingElement.attributes.filter(attr => attr !== vIfAttribute);
const condition = vIfAttribute.value.expression;
if (condition.type === 'JSXEmptyExpression')
return;
path.replaceWith(t.jsxExpressionContainer(t.conditionalExpression(condition, path.node, t.nullLiteral())));
}
function tablePlugin(path, t) {
var _a, _b, _c;
// 安全检查
if (!((_b = (_a = path.node) === null || _a === void 0 ? void 0 : _a.openingElement) === null || _b === void 0 ? void 0 : _b.name))
return;
// 检查是否是 Table 组件
if (path.node.openingElement.name.type !== 'JSXIdentifier' ||
path.node.openingElement.name.name !== 'Table') {
return;
}
// 检查是否已经有 sticky 属性
const hasSticky = path.node.openingElement.attributes.some((attr) => attr.type === "JSXAttribute" && attr.name.name === "sticky");
if (hasSticky)
return;
// 检查是否有 noBabel 属性且包含 'sticky'
const noBabelAttr = path.node.openingElement.attributes.find((attr) => attr.type === "JSXAttribute" && attr.name.name === "noBabel");
if (((_c = noBabelAttr === null || noBabelAttr === void 0 ? void 0 : noBabelAttr.value) === null || _c === void 0 ? void 0 : _c.type) === 'JSXExpressionContainer' &&
noBabelAttr.value.expression.type === 'ArrayExpression') {
const noBabelArray = noBabelAttr.value.expression.elements;
if (noBabelArray.some(element => (element === null || element === void 0 ? void 0 : element.type) === 'StringLiteral' && element.value === 'sticky')) {
return;
}
}
// 创建 sticky 属性
const stickyAttribute = t.jsxAttribute(t.jsxIdentifier("sticky"), t.jsxExpressionContainer(t.objectExpression([
t.objectProperty(t.identifier("offsetHeader"), t.numericLiteral(0))
])));
// 添加 sticky 属性到组件
path.node.openingElement.attributes.push(stickyAttribute);
}
function formColonPlugin(path, t) {
var _a, _b;
// 安全检查
if (!((_b = (_a = path.node) === null || _a === void 0 ? void 0 : _a.openingElement) === null || _b === void 0 ? void 0 : _b.name))
return;
// 检查是否是 Form 组件
if (path.node.openingElement.name.type !== 'JSXIdentifier' ||
path.node.openingElement.name.name !== 'Form') {
return;
}
// 查找现有的 colon 属性
const colonAttributeIndex = path.node.openingElement.attributes.findIndex((attr) => attr.type === "JSXAttribute" && attr.name.name === "colon");
// 创建强制设置为 false 的 colon 属性
const colonAttribute = t.jsxAttribute(t.jsxIdentifier("colon"), t.jsxExpressionContainer(t.booleanLiteral(false)));
if (colonAttributeIndex !== -1) {
// 如果已存在 colon 属性,替换它
path.node.openingElement.attributes[colonAttributeIndex] = colonAttribute;
}
else {
// 如果不存在 colon 属性,添加它
path.node.openingElement.attributes.push(colonAttribute);
}
}
const reactVIfPlugin = function (babel) {
return {
name: "babel-plugin-react-v-if",
visitor: {
JSXElement(path, state) {
// 处理v-if指令
vIfPlugin(path, babel.types);
// 处理Table组件的sticky属性
tablePlugin(path, babel.types);
// 处理Form组件的colon属性,强制设置为false
formColonPlugin(path, babel.types);
}
}
};
};
module.exports = reactVIfPlugin;