babel-plugin-transform-reblend-function-to-class
Version:
154 lines • 7.2 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const t = __importStar(require("@babel/types"));
const spreadBodyStatements_1 = __importDefault(require("./spreadBodyStatements"));
const spreadCustomHook_1 = __importDefault(require("./spreadCustomHook"));
const processHookMemberAccess_1 = require("./processHookMemberAccess");
const utils_1 = require("./utils");
const functionToClass = (path, state) => {
var _a, _b, _c;
const { node } = path;
let containSkipComment = false;
const comments = path.node.innerComments;
if (comments && comments.length > 0) {
for (const comment of comments || []) {
if (comment.value.includes(utils_1.TRANSFORMED_COMMENT.trim())) {
containSkipComment = true;
break;
}
}
}
// @ts-ignore
const functionName = node.id
? // @ts-ignore
node.id.name
: ((_a = path.parent) === null || _a === void 0 ? void 0 : _a.id)
? path.parent.id.name
: '';
const excludeHooks = [
'useState',
'useReducer',
'useRef',
'useMemo',
'useCallback',
'useEffect',
'useContext',
'useTransition',
'useEffectAfter',
'useProps',
];
if (!functionName ||
containSkipComment ||
node.type == 'ClassMethod' ||
excludeHooks.includes(functionName)) {
return;
}
if ((0, utils_1.isHookName)(functionName)) {
return (0, spreadCustomHook_1.default)(functionName, path, state);
}
let isBlockStatement = node.body.type === 'BlockStatement';
// Proceed with transformation only if no '@ReblendNotComponent' comment or "@ReblendComponent"
if (((0, utils_1.hasReblendComment)('Component', path) &&
!(0, utils_1.hasReblendComment)('NotComponent', path)) ||
(0, utils_1.isComponentName)(functionName)) {
path.addComment('inner', utils_1.TRANSFORMED_COMMENT, false);
const body = node.body.body || [];
const bodyStatements = [];
let renderReturnStatement = !isBlockStatement
? t.returnStatement(node.body)
: undefined;
body.forEach(statement => {
var _a, _b;
if (t.isReturnStatement(statement)) {
if (renderReturnStatement) {
throw new Error(`Reblend does not support conditional returns i.e Return statement should be the last statement in the function component ${functionName} ${path.hub.file.opts.filename}:${(_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line}:${(_b = node.loc) === null || _b === void 0 ? void 0 : _b.start.column}`);
}
renderReturnStatement = statement;
}
else {
bodyStatements.push(statement);
}
});
const stateAssignments = [];
const propsAssignments = [
//Props initializer
t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.thisExpression(), t.identifier('props')), t.objectExpression([]))),
];
let initPropsMethodArgument = (0, utils_1.getProps)(node);
if (initPropsMethodArgument.length > 1) {
throw new Error(`Reblend does not support multiple props parameter's for components
${functionName} ${path.hub.file.opts.filename}:${(_b = node.loc) === null || _b === void 0 ? void 0 : _b.start.line}:${(_c = node.loc) === null || _c === void 0 ? void 0 : _c.start.column}`);
}
const assignments = (0, spreadBodyStatements_1.default)(path, bodyStatements, initPropsMethodArgument);
propsAssignments.push(...assignments.props);
stateAssignments.push(...assignments.state);
const constructorMethod = t.classMethod('constructor', t.identifier('constructor'), [], t.blockStatement([
t.expressionStatement(t.callExpression(t.super(), [])),
]));
const initStateMethod = t.classMethod('method', t.identifier('initState'), [], t.blockStatement([...stateAssignments]), undefined, undefined, undefined, true);
const initPropsMethod = t.classMethod('method', t.identifier('initProps'), initPropsMethodArgument, t.blockStatement([...propsAssignments]), undefined, undefined, undefined, true);
const renderMethod = t.classMethod('method', t.identifier('html'), [], t.blockStatement([renderReturnStatement || t.returnStatement()]), undefined, undefined, undefined, true);
const classBody = [
t.classProperty(t.identifier('ELEMENT_NAME'), t.stringLiteral(functionName || 'Anonymous'), null, null, undefined, true),
constructorMethod,
initStateMethod,
initPropsMethod,
renderMethod,
];
const reblendImportNode = (0, utils_1.get)(state, utils_1.REBLEND_IMPORT_NAME_ID);
const reblendSuperNode = t.cloneNode(reblendImportNode);
const classDecl = t.classDeclaration(
//@ts-ignore
node.id ? t.identifier(node.id.name) : null, reblendSuperNode, t.classBody(classBody), []);
const classExpr = t.classExpression(
//@ts-ignore
node.id ? t.identifier(node.id.name) : null, reblendSuperNode, t.classBody(classBody), []);
path.scope.removeBinding(functionName);
//@ts-ignore
if (t.isExpression(path)) {
path.replaceWith(classExpr);
}
else {
path.replaceWith(classDecl);
}
(0, processHookMemberAccess_1.processHookMemberAccess)(path);
}
};
exports.default = functionToClass;
//# sourceMappingURL=functionToClass.js.map