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