database-petani-mobile/node_modules/@base44/vite-plugin/dist/processors/static-array-processor.js
2026-02-23 16:39:35 +07:00

175 lines
6.4 KiB
JavaScript

import { JSXAttributeUtils, StaticValueUtils } from "./shared-utils.js";
export const DATA_ARR_INDEX = "data-arr-index";
export const DATA_ARR_VARIABLE_NAME = "data-arr-variable-name";
export const DATA_ARR_FIELD = "data-arr-field";
const GENERATED_INDEX_PARAM = "__arrIdx__";
export class StaticArrayProcessor {
types;
attributeUtils;
staticValueUtils;
constructor(types) {
this.types = types;
this.attributeUtils = new JSXAttributeUtils(types);
this.staticValueUtils = new StaticValueUtils(types);
}
process(path) {
const arrayInfo = this.findParentArrayMap(path);
if (!arrayInfo)
return;
if (!this.isStaticArray(arrayInfo.arrayExpression))
return;
const indexIdentifier = this.ensureIndexParam(arrayInfo);
this.addDataAttributes(path, arrayInfo, indexIdentifier);
}
addDataAttributes(path, arrayInfo, indexIdentifier) {
this.attributeUtils.addExpressionAttribute(path, DATA_ARR_INDEX, this.types.identifier(indexIdentifier));
if (arrayInfo.arrayVariableName) {
this.attributeUtils.addStringAttribute(path, DATA_ARR_VARIABLE_NAME, arrayInfo.arrayVariableName);
}
const fieldPath = this.findTextContentFieldPath(path, arrayInfo.callbackParam);
if (fieldPath) {
this.attributeUtils.addStringAttribute(path, DATA_ARR_FIELD, fieldPath);
}
}
findTextContentFieldPath(path, callbackParam) {
const parentElement = path.parentPath;
if (!parentElement?.isJSXElement())
return null;
for (const child of parentElement.get("children")) {
const fieldPath = this.extractFieldPathFromChild(child, callbackParam);
if (fieldPath)
return fieldPath;
}
return null;
}
extractFieldPathFromChild(child, callbackParam) {
if (!child.isJSXExpressionContainer())
return null;
const expression = child.get("expression");
if (!expression.isMemberExpression())
return null;
return this.extractFieldPath(expression, callbackParam);
}
extractFieldPath(expr, callbackParam) {
const parts = this.collectMemberExpressionParts(expr);
if (!parts)
return null;
const { rootName, propertyNames } = parts;
return rootName === callbackParam ? propertyNames.join(".") : null;
}
collectMemberExpressionParts(expr) {
const propertyNames = [];
let current = expr;
while (current.isMemberExpression()) {
const property = current.get("property");
if (!property.isIdentifier())
return null;
propertyNames.unshift(property.node.name);
current = current.get("object");
}
if (!current.isIdentifier())
return null;
return { rootName: current.node.name, propertyNames };
}
ensureIndexParam(arrayInfo) {
if (arrayInfo.indexParam) {
return arrayInfo.indexParam;
}
this.addIndexParamToCallback(arrayInfo.mapCallPath);
return GENERATED_INDEX_PARAM;
}
addIndexParamToCallback(mapCallPath) {
const callback = this.getMapCallback(mapCallPath);
if (!callback)
return;
const params = callback.get("params");
if (params.length === 1) {
callback.node.params.push(this.types.identifier(GENERATED_INDEX_PARAM));
}
}
getMapCallback(mapCallPath) {
const args = mapCallPath.get("arguments");
const firstArg = args[0];
if (firstArg && firstArg.isFunction()) {
return firstArg;
}
return null;
}
findParentArrayMap(path, maxDepth = 5) {
let currentPath = path;
let depth = 0;
while (currentPath.parentPath && depth < maxDepth) {
const mapInfo = this.tryExtractMapInfo(currentPath.parentPath);
if (mapInfo)
return mapInfo;
currentPath = currentPath.parentPath;
depth++;
}
return null;
}
tryExtractMapInfo(parent) {
if (!parent.isCallExpression())
return null;
if (!this.isMapCall(parent))
return null;
return this.extractArrayMapInfo(parent);
}
isMapCall(callExpr) {
const callee = callExpr.get("callee");
if (!callee.isMemberExpression())
return false;
const property = callee.get("property");
return property.isIdentifier() && property.node.name === "map";
}
extractArrayMapInfo(mapCall) {
const callback = this.getMapCallback(mapCall);
if (!callback)
return null;
const params = callback.get("params");
const firstParam = params[0];
if (!firstParam || !firstParam.isIdentifier())
return null;
const callee = mapCall.get("callee");
const arrayExpression = callee.get("object");
return {
arrayExpression,
callbackParam: firstParam.node.name,
indexParam: this.extractIndexParam(params),
arrayVariableName: this.extractArrayVariableName(arrayExpression),
mapCallPath: mapCall,
};
}
extractIndexParam(params) {
const secondParam = params[1];
return secondParam && secondParam.isIdentifier()
? secondParam.node.name
: null;
}
extractArrayVariableName(arrayExpression) {
return arrayExpression.isIdentifier() ? arrayExpression.node.name : null;
}
isStaticArray(arrayExpression) {
const arrayExpr = this.resolveArrayExpression(arrayExpression);
return arrayExpr ? this.isStaticArrayExpression(arrayExpr) : false;
}
resolveArrayExpression(expression) {
if (expression.isArrayExpression()) {
return expression;
}
if (expression.isIdentifier()) {
return this.resolveIdentifierToArray(expression);
}
return null;
}
resolveIdentifierToArray(identifier) {
const binding = identifier.scope.getBinding(identifier.node.name);
if (!binding?.path.isVariableDeclarator())
return null;
const init = binding.path.get("init");
return init.isArrayExpression() ? init : null;
}
isStaticArrayExpression(arrayExpression) {
return this.staticValueUtils.isStaticArrayExpression(arrayExpression);
}
}
//# sourceMappingURL=static-array-processor.js.map