diff --git a/app/srv/package.json b/app/srv/package.json index e58a57d8..2df086ed 100644 --- a/app/srv/package.json +++ b/app/srv/package.json @@ -7,6 +7,7 @@ "@node-rs/argon2": "^1.5.2", "@paralleldrive/cuid2": "^2.2.2", "@types/mime-types": "^2.1.2", + "recast": "^0.23.4", "esbuild": "^0.19.4", "lmdb": "^2.8.5", "mime-types": "^2.1.35", diff --git a/app/srv/ws/sync/actions/swc_parse.ts b/app/srv/ws/sync/actions/swc_parse.ts index 6f1f486a..13cf6787 100644 --- a/app/srv/ws/sync/actions/swc_parse.ts +++ b/app/srv/ws/sync/actions/swc_parse.ts @@ -1,5 +1,6 @@ import { IContent } from "../../../../web/src/utils/types/general"; import { SAction } from "../actions"; +import { parseJs } from "../editor/parser/parse-js"; import { docs } from "../entity/docs"; import { SyncConnection } from "../type"; @@ -11,9 +12,32 @@ export const swc_parse: SAction["swc"]["parse"] = async function ( let ydoc = docs.page[arg.page_id]; if (ydoc) { const item = ydoc.doc.getMap("map").get("root")?.toJSON() as IContent; + const res = parseItem(item); + console.log(res); } - } + } let result = null as unknown as Awaited>; - return result; + return result; +}; + +type ParseParent = Record; +export const parseItem = (item: IContent, _parents?: ParseParent) => { + const parents = _parents || {}; + + const js = item.adv?.js; + if (typeof js === "string") { + const res = parseJs(js); + if (res) { + parents[item.id] = res; + } + } + + if (item.type !== "text") { + for (const c of item.childs) { + parseItem(c, parents); + } + } + + return parents; }; diff --git a/app/srv/ws/sync/editor/parser/parse-js.ts b/app/srv/ws/sync/editor/parser/parse-js.ts new file mode 100644 index 00000000..b3147892 --- /dev/null +++ b/app/srv/ws/sync/editor/parser/parse-js.ts @@ -0,0 +1,76 @@ +import recast from "recast"; +import babel from "recast/parsers/babel-ts"; +export const parseJs = (code: string) => { + const ast = recast.parse(code, { + parser: babel, + }); + + const local = { name: "", value: "", index: 0 }; + const passprop: any = {}; + 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; + 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.name.name === "value" && + attr.value && + 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; + }, + }); + + const result: any = {}; + if (local.name) { + result.local = local; + } + if (Object.keys(passprop).length > 0) { + result.passprop = passprop; + } + + if (Object.keys(result).length > 0) { + return result; + } +}; diff --git a/bun.lockb b/bun.lockb index 82cde963..5781147b 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 0e3d9d17..4f9717e1 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "dependencies": { "brotli-wasm": "^2.0.1", "fdir": "^6.1.0", - "oxc-parser": "^0.2.0", "typescript": "^5.2.2" } }