UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

722 lines 37.1 kB
"use strict"; 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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseNaturalTSXView = exports.transformTSDeclareFunction2View = exports.transform2View = exports.transformJSXElement2ViewElement = exports.transform2Variables = void 0; /* eslint-disable global-require */ /* eslint-disable @typescript-eslint/no-use-before-define */ const utils_1 = require("./transforms/utils"); const lodash_1 = require("lodash"); const babel = __importStar(require("@babel/core")); const utils_2 = require("../utils"); const transform2TypeAnnotation_1 = require("./transforms/transform2TypeAnnotation"); const transform2LogicItem_1 = require("./transforms/transform2LogicItem"); const transform2Logic_1 = require("./transforms/transform2Logic"); const transform2ValidationRule_1 = require("./transforms/transform2ValidationRule"); const transformThemeAndStyle_1 = require("./transforms/transformThemeAndStyle"); function transform2Variables(node, options) { const variables = []; const declList = node?.declarations || []; declList.forEach((decl) => { const variableName = decl.id.name; let typeAnnotation = (0, transform2TypeAnnotation_1.transform2TypeAnnotation)(decl.id.typeAnnotation?.typeAnnotation, options) || undefined; const variable = new utils_1.naslTypes.Variable({ name: variableName, typeAnnotation, }); if (decl.init) { variable.defaultValue = new utils_1.naslTypes.DefaultValue({ expression: (0, transform2LogicItem_1.transform2LogicItem)(decl.init, { ...options, transformType: 'attr', typeAnnotation, isRestricted: true, isInFrontend: true }), }); } variables.push(variable); }); return variables; } exports.transform2Variables = transform2Variables; function transform2EventLogics(node, eventName, options) { if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') { const logic = (0, transform2Logic_1.transform2Logic)(node, eventName, { ...options, logicType: 'event_logic' }); logic.params = []; return [logic]; } else if (node.type === 'CallExpression') { if (node.callee.type === 'Identifier' && node.callee.name === '$all') { const args = node.arguments; return args.map((node) => { if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') { const logic = (0, transform2Logic_1.transform2Logic)(node, eventName, { ...options, logicType: 'event_logic' }); logic.params = []; return logic; } else { return (0, utils_1.throwError)(options, '事件逻辑参数不支持的类型', node.type, node); } }).filter(Boolean); } else { return (0, utils_1.throwError)(options, '事件逻辑参数不正确', node); } } else if (node.type === 'Identifier' || node.type === 'MemberExpression') { return (0, utils_1.throwError)(options, '事件逻辑参数不正确,不支持绑定逻辑,需要直接写在元素中', node); } else { return (0, utils_1.throwError)(options, '事件逻辑参数不正确', node); } } function handleDirectoryItem(directoryItem, nextStatement, view, options, callerName) { let definitionItem = null; if (nextStatement.type === 'VariableDeclaration') { // 处理变量声明 const variables = transform2Variables(nextStatement, options); definitionItem = variables[0]; } else if (nextStatement.type === 'FunctionDeclaration') { // 处理函数/逻辑声明 definitionItem = (0, transform2Logic_1.transform2Logic)(nextStatement, undefined, { ...options, logicType: 'view_logic' }); } else { const functionName = callerName || '$Variable'; (0, utils_1.throwError)(options, `${functionName} 后面必须跟变量声明或函数声明`, nextStatement); } if (!definitionItem) return null; const referredConcept = definitionItem.concept; const definition = new utils_1.naslTypes.ReferredDefinition({ referredConcept, name: definitionItem.name, namespace: '', }); // 将定义添加到目录 if (!view.directories?.find((dir) => dir.name === directoryItem.name)) { directoryItem.definitions = [definition]; view.addDirectory(directoryItem); } else { const existingDirectory = view.directories.find((dir) => dir.name === directoryItem.name); const hasDefinition = existingDirectory?.definitions.find((def) => def.name === definitionItem.name && def.referredConcept === referredConcept); if (!hasDefinition) { existingDirectory?.definitions.push(definition); } } // 将实际的变量或逻辑添加到视图 if (referredConcept === 'Variable') { view.addVariable(definitionItem); } else if (referredConcept === 'Logic') { view.addLogic(definitionItem); } return definitionItem; } function transformJSXElement2ViewElement(node, options) { const el = node.openingElement; if (el.name.type === 'JSXIdentifier') { let tag = (0, lodash_1.kebabCase)(el.name.name); if (tag === 'el-form-date-time-picker') tag = 'el-form-date-picker'; if (tag === 'el-form-input-date') tag = 'el-form-date-picker'; if (tag === 'el-form-textarea') tag = 'el-form-input'; if (tag === 'el-form-item') tag = 'el-form-input'; const viewElement = new utils_1.naslTypes.ViewElement({ tag, }); const attrs = el.attributes; let directivePrefix = '$'; let eventPrefix = 'on'; let slotPrefix = 'slot'; function addJSXChild(node, slotTarget = 'default', slotScope = '') { if (node.type === 'JSXElement') { if (slotTarget === 'default' && !slotScope) { const child = transformJSXElement2ViewElement(node, options); child && viewElement.children.push(child); } else { const child = transformJSXElement2ViewElement(node, options); let templateName = 'template_' + (0, utils_2.uuidv4)().slice(0, 5); // 确保模板名称也不重复 while (options.nameMap.has(templateName)) { templateName = 'template_' + (0, utils_2.uuidv4)().slice(0, 5); } options.nameMap.set(templateName, true); const templateChild = new utils_1.naslTypes.ViewElement({ tag: 'template', name: templateName, slotTarget, slotScope, children: child ? [child] : [], }); if (viewElement.children.some((child) => child.tag === 'template' && child.slotTarget === slotTarget)) (0, utils_1.throwError)(options, `slot${(0, utils_2.firstUpperCase)(slotTarget)} 不能重复`, node); viewElement.children.push(templateChild); } } else if (node.type === 'JSXFragment') { const children = node.children; if (slotTarget === 'default' && !slotScope) { viewElement.children.push(...children.filter((child) => child.type === 'JSXElement').map((child) => transformJSXElement2ViewElement(child, options)).filter(Boolean)); } else { let templateName = 'template_' + (0, utils_2.uuidv4)().slice(0, 5); // 确保模板名称也不重复 while (options.nameMap.has(templateName)) { templateName = 'template_' + (0, utils_2.uuidv4)().slice(0, 5); } options.nameMap.set(templateName, true); const templateChild = new utils_1.naslTypes.ViewElement({ tag: 'template', name: templateName, slotTarget, slotScope, children: children.filter((child) => child.type === 'JSXElement').map((child) => transformJSXElement2ViewElement(child, options)).filter(Boolean), }); if (viewElement.children.some((child) => child.tag === 'template' && child.slotTarget === slotTarget)) (0, utils_1.throwError)(options, `slot${(0, utils_2.firstUpperCase)(slotTarget)} 不能重复`, node); viewElement.children.push(templateChild); } } else { return (0, utils_1.throwError)(options, '不支持的JSX子元素类型', node); } } function addArrowFunctionJSXChild(node, slotTarget = 'default') { const slotScopeName = node.params[0]?.name; if (slotScopeName && slotScopeName !== 'current' && !slotScopeName?.startsWith('current')) { return (0, utils_1.throwError)(options, `slotScope 需以 current 参数名开头`, node); } let slotScope = ''; if (slotScopeName) { slotScope = 'current'; } const body = node.body; if (body.type === 'JSXElement' || body.type === 'JSXFragment') { addJSXChild(body, slotTarget, slotScope); } else if (body.type === 'ArrayExpression') { const elements = body.elements; elements.forEach((element) => { addJSXChild(element, slotTarget, slotScope); }); } else { return (0, utils_1.throwError)(options, '不支持的JSX子元素类型', body.type, body); } } attrs.forEach((attr) => { if (attr.type === 'JSXAttribute') { const attrName = attr.name.name; if (!attrName) (0, utils_1.throwError)(options, '属性名不能为空', attr); if (attrName === 'ref') { if (attr.value?.type === 'StringLiteral') { const proposedName = attr.value.value; if (options.nameMap.has(proposedName)) { return (0, utils_1.throwError)(options, `ref 属性值 "${proposedName}" 已存在,不能重复使用`, attr); } viewElement.name = proposedName; options.nameMap.set(proposedName, true); } else { return (0, utils_1.throwError)(options, 'ref 属性值不正确', attr.value); } } else if (attrName === 'style') { if (attr.value?.type === 'StringLiteral') { viewElement.staticStyle = attr.value.value; } else { return (0, utils_1.throwError)(options, 'style 属性只能用字符串字面量', attr.value); } } else if (attrName === '$extraStyle') { if (!attr.value) { (0, utils_1.throwError)(options, '$extraStyle 属性只能用字符串字面量', attr); } else if (attr.value.type === 'StringLiteral') { viewElement.cssRules = (0, transformThemeAndStyle_1.transformStyle)(attr.value.value, options); } else if (attr.value.type === 'JSXExpressionContainer') { const templateLiteral = attr.value.expression; if (templateLiteral.type === 'TemplateLiteral') { if (templateLiteral.expressions.length > 0) { return (0, utils_1.throwError)(options, '不支持在 $theme 中使用动态表达式'); } const css = templateLiteral.quasis[0].value.raw; viewElement.cssRules = (0, transformThemeAndStyle_1.transformStyle)(css, options); } else { return (0, utils_1.throwError)(options, '$extraStyle 属性只能用字符串字面量', attr.value); } } else { return (0, utils_1.throwError)(options, '$extraStyle 属性只能用字符串字面量', attr.value); } } else if (attrName === '$dynamicStyle') { if (!attr.value) { (0, utils_1.throwError)(options, '$dynamicStyle 属性只能用字符串字面量', attr); } else if (attr.value.type === 'JSXExpressionContainer') { const expression = attr.value.expression; if (expression.type === 'ObjectExpression') { const properties = expression.properties; properties.forEach((property) => { if (property.type === 'ObjectProperty') { const name = (0, lodash_1.kebabCase)(property.key.name); viewElement.bindStyles = viewElement.bindStyles || []; viewElement.addBindStyle(new utils_1.naslTypes.BindStyle({ name, expression: (0, transform2LogicItem_1.transform2LogicItem)(property.value, { ...options, transformType: 'attr', isRestricted: true, isInFrontend: true, }), })); } }); } } else { return (0, utils_1.throwError)(options, 'style 属性值不正确', attr.value); } } else if (attrName.startsWith(directivePrefix)) { const directiveName = attrName.slice(directivePrefix.length); const directive = new utils_1.naslTypes.BindDirective({ name: directiveName, }); if (!attr.value) { directive.type = 'static'; directive.value = 'true'; } else if (attr.value.type === 'StringLiteral') { directive.type = 'string'; directive.value = attr.value.value; } else if (attr.value.type === 'JSXExpressionContainer') { if (attr.value.expression.type === 'BooleanLiteral' || attr.value.expression.type === 'NumericLiteral' || attr.value.expression.type === 'NullLiteral' || attr.value.expression.type === 'StringLiteral') { directive.type = 'static'; directive.value = (0, utils_1.generate)(attr.value.expression).code; } else { directive.type = 'dynamic'; if (attr.value.expression.type === 'FunctionExpression') return (0, utils_1.throwError)(options, '指令不支持传函数表达式', attr); directive.expression = (0, transform2LogicItem_1.transform2LogicItem)(attr.value.expression, { ...options, transformType: 'attr', isRestricted: true, isInFrontend: true, }); } } else { return (0, utils_1.throwError)(options, '不支持的指令类型', attr.value.type, attr.value); } if (directiveName !== 'for') { viewElement.addBindDirective(directive); } } else if (attrName.startsWith(eventPrefix)) { const eventName = (0, utils_2.firstLowerCase)(attrName.slice(eventPrefix.length)); if (attr.value?.type === 'JSXExpressionContainer') { const bindEvent = new utils_1.naslTypes.BindEvent({ name: eventName, logics: transform2EventLogics(attr.value.expression, eventName, options) || [], }); viewElement.addBindEvent(bindEvent); } else { return (0, utils_1.throwError)(options, '事件逻辑参数不正确', attr.value); } } else if (attrName.startsWith(slotPrefix)) { const slotTarget = (0, utils_2.firstLowerCase)(attrName.slice(slotPrefix.length)); if (attr.value?.type === 'JSXExpressionContainer') { const expression = attr.value.expression; if (expression.type === 'JSXElement' || expression.type === 'JSXFragment') { addJSXChild(expression, slotTarget); } else if (expression.type === 'ArrowFunctionExpression') { addArrowFunctionJSXChild(expression, slotTarget); } else { return (0, utils_1.throwError)(options, 'slot 属性值不正确', attr.value); } } } else if (attrName === 'rules') { const bindAttribute = new utils_1.naslTypes.BindAttribute({ name: attrName, }); if (attr.value?.type === 'JSXExpressionContainer') { if (attr.value.expression.type === 'ArrayExpression') { const elements = attr.value.expression.elements; bindAttribute.rules = elements.map((node) => (0, transform2ValidationRule_1.transform2ValidationRule)(node, options)).filter(Boolean); } else if (attr.value.expression.type === 'CallExpression') { const callee = (0, utils_1.generate)(attr.value.expression.callee).code; if (callee === 'nasl.util.NewList' || callee === 'NewList') { const elements = attr.value.expression.arguments[0].elements; bindAttribute.rules = elements.map((node) => (0, transform2ValidationRule_1.transform2ValidationRule)(node, options)).filter(Boolean); } else { return (0, utils_1.throwError)(options, 'rules 属性值不正确', attr.value); } } else { return (0, utils_1.throwError)(options, 'rules 属性值不正确', attr.value); } } else { return (0, utils_1.throwError)(options, 'rules 属性值不正确', attr.value); } viewElement.addBindAttribute(bindAttribute); } else { const bindAttribute = new utils_1.naslTypes.BindAttribute({ name: attrName, }); if (!attr.value) { bindAttribute.type = 'static'; bindAttribute.value = 'true'; } else if (attr.value.type === 'StringLiteral') { bindAttribute.type = 'string'; bindAttribute.value = attr.value.value; } else if (attr.value.type === 'JSXExpressionContainer') { if (attr.value.expression.type === 'BooleanLiteral' || attr.value.expression.type === 'NumericLiteral' || attr.value.expression.type === 'NullLiteral' || attr.value.expression.type === 'StringLiteral') { bindAttribute.type = 'static'; bindAttribute.value = (0, utils_1.generate)(attr.value.expression).code; } else { let expr = attr.value.expression; if (attrName === 'prop' || attrName.endsWith('Field')) { if (expr.type === 'ArrowFunctionExpression') { bindAttribute.type = 'string'; const paramName = expr.params[0]?.name || 'item'; const code = (0, utils_1.generate)(expr.body).code; bindAttribute.value = code.replace(new RegExp(`${paramName}\\.`, 'g'), ''); if (bindAttribute.value === 'item' && code !== 'item.item') bindAttribute.value = ''; viewElement.addBindAttribute(bindAttribute); return; } } bindAttribute.type = 'dynamic'; if (expr.type === 'CallExpression' && expr.callee.type === 'Identifier' && expr.callee.name === '$sync') { bindAttribute.sync = true; if (expr.arguments.length === 0) { return (0, utils_1.throwError)(options, '$sync 的参数不能为空', attr); } else if (expr.arguments.length > 0) { expr = expr.arguments[0]; if (!expr) return (0, utils_1.throwError)(options, '$sync 的参数不能为空', attr); } } if (expr.type === 'FunctionExpression') return (0, utils_1.throwError)(options, '属性不支持传函数表达式', attr); const expression = (0, transform2LogicItem_1.transform2LogicItem)(expr, { ...options, transformType: 'attr', isRestricted: attrName !== 'dataSource', isInFrontend: true, }); if (expression?.concept === 'Destination') { bindAttribute.destination = expression; } else if (expression?.concept === 'ExternalDestination') { bindAttribute.externalDestination = expression; } else { bindAttribute.expression = expression; } } } else { return (0, utils_1.throwError)(options, '不支持的指令类型', attr.value.type, attr.value); } viewElement.addBindAttribute(bindAttribute); } } else { return (0, utils_1.throwError)(options, '不支持的JSX属性类型', attr.type, attr); } }); { /* 临时补救 EnumToList 问题 */ if (viewElement.bindAttrs.some((bindAttr) => bindAttr.name === 'dataSource' && bindAttr.expression?.concept === 'CallFunction' && bindAttr.expression?.calleeName === 'EnumToList')) { const index = viewElement.bindAttrs.findIndex((bindAttr) => bindAttr.name === 'valueField'); ~index && viewElement.bindAttrs.splice(index, 1); } } node.children.forEach((child) => { if (child.type === 'JSXElement' || child.type === 'JSXFragment') { addJSXChild(child); } else if (child.type === 'JSXExpressionContainer') { const expression = child.expression; if (expression.type === 'JSXElement' || expression.type === 'JSXFragment') { addJSXChild(expression); } else if (expression.type === 'ArrowFunctionExpression') { addArrowFunctionJSXChild(expression); } else if (expression.type === 'JSXEmptyExpression') { // ignore } else { return (0, utils_1.throwError)(options, '不支持的JSX子元素类型', expression.type, expression); } } else if (child.type === 'JSXText') { // ignore } else { return (0, utils_1.throwError)(options, '不支持的JSX子元素类型', child.type, child); } }); if (!viewElement.name) { let generatedName = viewElement.tag.replace(/-/g, '_') + '_' + (0, utils_2.uuidv4)().slice(0, 5); // 确保生成的名称也不重复 while (options.nameMap.has(generatedName)) { generatedName = viewElement.tag.replace(/-/g, '_') + '_' + (0, utils_2.uuidv4)().slice(0, 5); } viewElement.name = generatedName; options.nameMap.set(generatedName, true); } return viewElement; } else { return (0, utils_1.throwError)(options, '不支持的JSX元素类型', el.name.type, el); } } exports.transformJSXElement2ViewElement = transformJSXElement2ViewElement; function transform2View(func, decorator, options) { const statements = func.body.body; // 为每个视图创建独立的 nameMap const nameMap = new Map(); const view = new utils_1.naslTypes.View({ name: func.id?.name, }); options.nodeName = view.name; const opts = { ...options, nameMap }; if (decorator) { if (decorator.arguments[0].type === 'ObjectExpression') { const viewObj = (0, utils_1.pickDecoratorObject)(decorator.arguments[0], new Set([ 'pageTemplateId', 'uuid', 'title', 'crumb', 'auth', 'authDescription', 'isIndex', ]), options); Object.assign(view, viewObj); view.crumb = new utils_1.naslTypes.StaticString({ value: viewObj.crumb, }); } else { return (0, utils_1.throwError)(options, '不支持的装饰器类型', decorator.type, decorator); } } func.params.forEach((param) => { if (param.type === 'Identifier') { const _param = (0, transform2LogicItem_1.transform2Param)(param, { ...options, transformType: 'attr' }); _param && view.params.push(_param); } else if (param.type === 'ObjectPattern') { const propertyMap = {}; param.properties.forEach((property) => { if (property.type === 'ObjectProperty') { if (property.value.type === 'Identifier') { propertyMap[property.value.name] = { type: 'AssignmentPattern', left: property.value, right: undefined, }; } else if (property.value.type === 'AssignmentPattern') { propertyMap[property.value.left.name] = property.value; } else { return (0, utils_1.throwError)(options, '不支持的参数类型', property.value.type, property.value); } } }); const type = param.typeAnnotation?.typeAnnotation; if (!type) return (0, utils_1.throwError)(options, 'param 没有对应的类型', param); type.members.forEach((member) => { if (member.type === 'TSPropertySignature') { const name = member.key.name; if (propertyMap[name]) { propertyMap[name].left.typeAnnotation = member.typeAnnotation; } } }); Object.values(propertyMap).forEach((property) => { const param = (0, transform2LogicItem_1.transform2Param)(property, { ...options, transformType: 'attr' }); param && view.params.push(param); }); } }); for (let index = 0; index < statements.length; index++) { const statement = statements[index]; if (statement.type === 'VariableDeclaration') { const variables = transform2Variables(statement, { ...options }); variables.forEach((variable) => { view.addVariable(variable); }); } else if (statement.type === 'FunctionDeclaration') { const logic = (0, transform2Logic_1.transform2Logic)(statement, undefined, { ...options, logicType: 'view_logic' }); view.addLogic(logic); } else if (statement.type === 'ExpressionStatement' && statement.expression.type === 'CallExpression') { const expression = statement.expression; if (expression.callee.type == 'Identifier' && expression.callee.name.startsWith('on')) { const eventName = (0, utils_2.firstLowerCase)(expression.callee.name.slice(2)); const arg = expression.arguments[0]; const bindEvent = new utils_1.naslTypes.BindEvent({ name: eventName, logics: transform2EventLogics(arg, eventName, { ...options }) || [], }); view.addBindEvent(bindEvent); } else if (expression.callee.type == 'Identifier' && expression.callee.name.startsWith('$')) { if (expression?.arguments[0]?.type === 'ObjectExpression') { const { properties } = expression?.arguments[0]; const directoryNode = properties.find((item) => item.key?.name === 'directory'); if (directoryNode) { const directoryItem = (0, transform2LogicItem_1.transformNode2Directory)(directoryNode); if (directoryItem) { const nextStatement = statements[index + 1]; if (nextStatement) { const definitionItem = handleDirectoryItem(directoryItem, nextStatement, view, { ...options }, expression.callee.name); if (definitionItem) { // 跳过下一个语句,因为已经处理过了 index++; } } } else { return (0, utils_1.throwError)(options, '不支持的定义类型', directoryNode); } } } else { return (0, utils_1.throwError)(options, '不支持的表达式', statement); } } else { return (0, utils_1.throwError)(options, '不支持的表达式', statement); } } else if (statement.type === 'ReturnStatement') { const arg = statement.argument; if (arg.type === 'JSXElement') { const child = transformJSXElement2ViewElement(arg, opts); view.elements = child ? [child] : []; } else if (arg.type === 'JSXFragment') { view.elements = arg.children.filter((child) => child.type === 'JSXElement').map((child) => transformJSXElement2ViewElement(child, opts)).filter(Boolean); } else { return (0, utils_1.throwError)(options, '返回值不正确', arg); } } else { return (0, utils_1.throwError)(options, '不支持的表达式', statement); } } return view; } exports.transform2View = transform2View; function transformTSDeclareFunction2View(func, decorator, options) { const view = new utils_1.naslTypes.View({ name: func.id?.name, }); options.nodeName = view.name; if (decorator) { if (decorator.arguments[0].type === 'ObjectExpression') { const viewObj = (0, utils_1.pickDecoratorObject)(decorator.arguments[0], new Set([ 'pageTemplateId', 'uuid', 'title', 'crumb', 'auth', 'authDescription', 'isIndex', ]), options); Object.assign(view, viewObj); view.crumb = new utils_1.naslTypes.StaticString({ value: viewObj.crumb, }); } else { return (0, utils_1.throwError)(options, '不支持的装饰器类型', decorator.type, decorator); } } func.params.forEach((param) => { if (param.type === 'Identifier') { const _param = (0, transform2LogicItem_1.transform2Param)(param, { ...options, transformType: 'attr' }); _param && view.params.push(_param); } }); return view; } exports.transformTSDeclareFunction2View = transformTSDeclareFunction2View; function parseNaturalTSXView(tsCode, options) { const root = babel.parseSync(tsCode, { filename: 'result.tsx', presets: [require('@babel/preset-typescript')], }); let func; let funcIndex = 0; let decorator; root.program.body.forEach((statement, index) => { if (statement.type === 'ExportNamedDeclaration' && statement.declaration.type === 'FunctionDeclaration') { func = statement.declaration; funcIndex = index; } else if (statement.type === 'FunctionDeclaration') { func = statement; funcIndex = index; } const prevStatement = root.program.body[index - 1]; if (prevStatement?.type === 'ExpressionStatement' && prevStatement.expression.type === 'CallExpression' && prevStatement.expression.callee.type === 'Identifier' && prevStatement.expression.callee.name === '$View') { decorator = prevStatement.expression; } }); return transform2View(func, decorator, options); } exports.parseNaturalTSXView = parseNaturalTSXView; //# sourceMappingURL=parseNaturalTSXView.js.map