prasi-bun/app/srv/ws/sync/editor/parser/parse-js.ts

122 lines
3.6 KiB
TypeScript

import recast from "recast";
import babel from "recast/parsers/babel-ts";
import { IItem, MItem } from "../../../../../web/src/utils/types/item";
import { EdMeta } from "../../../../../web/src/nova/ed/logic/ed-global";
export type ArgParentMComp = EdMeta["parent_mcomp"] & {
id: string;
parent_ids: string[];
jsx_props: Record<
string,
{
id: string;
mitem: MItem;
parent_mcomp?: ArgParentMComp;
parent_ids: string[];
}
>;
};
export const parseJs = (
code: string,
arg: {
item: IItem;
content_scope?: Record<string, string>;
}
) => {
const { item } = arg;
const local = { name: "", value: "", index: 0 };
const passprop: Record<string, { value: string; index: number }> = {};
const result = {} as {
local: typeof local | undefined;
passprop: typeof passprop | undefined;
props: Record<string, { name: string; value: string }>;
};
try {
const ast = recast.parse(code, {
parser: babel,
});
recast.visit(ast, {
visitJSXOpeningElement({ node }) {
if (node.name.type === "JSXIdentifier" && node.attributes) {
if (node.name.name === "Local") {
for (const attr of node.attributes) {
if (
attr.type === "JSXAttribute" &&
attr.name.type === "JSXIdentifier"
) {
if (
attr.name.name === "name" &&
attr.value?.type === "StringLiteral"
) {
local.name = attr.value.value;
}
if (
attr.name.name === "value" &&
attr.value &&
attr.value.type === "JSXExpressionContainer" &&
attr.value.expression.type === "ObjectExpression" &&
attr.value.expression.loc
) {
const loc = attr.value.expression.loc as any;
const start = attr.value.expression.properties[0].loc?.start;
const end =
attr.value.expression.properties[
attr.value.expression.properties.length - 1
].loc?.end;
if (typeof start === "number" && typeof end === "number") {
local.value = code.substring(
loc.start.index,
loc.end.index
);
local.index = loc.start.index;
}
}
}
}
} else if (node.name.name === "PassProp") {
for (const attr of node.attributes) {
if (
attr.type === "JSXAttribute" &&
attr.name.type === "JSXIdentifier"
) {
if (attr.value) {
if (
attr.value.type === "JSXExpressionContainer" &&
attr.value.expression.loc
) {
const loc = attr.value.expression.loc as any;
passprop[attr.name.name] = {
value: code.substring(loc.start.index, loc.end.index),
index: loc.start.index,
};
}
}
}
}
}
}
return true;
},
});
if (local.name) {
result.local = local;
}
if (Object.keys(passprop).length > 0) {
result.passprop = passprop;
}
if (Object.keys(result).length > 0) {
return result;
}
} catch (e) {
// console.error(code, "\n", e);
}
return result;
};