diff --git a/app/web/src/nova/ed/panel/popup/script/monaco.tsx b/app/web/src/nova/ed/panel/popup/script/monaco.tsx index 975eb325..2d78b497 100644 --- a/app/web/src/nova/ed/panel/popup/script/monaco.tsx +++ b/app/web/src/nova/ed/panel/popup/script/monaco.tsx @@ -15,6 +15,7 @@ import { declareScope } from "./scope/scope"; import { Loading } from "../../../../../utils/ui/loading"; // @ts-ignore import { constrainedEditor } from "constrained-editor-plugin/dist/esm/constrainedEditor"; +import { addScope } from "./scope/add-scope"; const scriptEdit = { timeout: null as any, @@ -110,41 +111,34 @@ export const EdScriptMonaco: FC<{}> = () => { ); editor.setModel(nmodel); } else { - const imports = declareScope(p, meta, monaco); - let cur = active.comp_id ? active.comp_id : "page"; - monaco.editor.getModels().forEach((model) => { - if ( - type === "item" && - model.uri.path === `/${cur}_${active.item_id}_src_src.tsx` - ) { - editor.setModel(model); - } - - if ( - type === "prop-instance" && - model.uri.path === - `/${cur}_${active.item_id}_prop_${p.ui.popup.script.prop_name}.tsx` - ) { - editor.setModel(model); - } - }); - const model = editor.getModel(); - if (!model) { - const nmodel = monaco.editor.createModel( - imports && imports.length > 0 - ? `${imports}\n/** IMPORT MODULE **/\n${val}` - : val, - "typescript", - monaco.Uri.parse("file:///active.tsx") - ); - editor.setModel(nmodel); - } - if (imports) { - local.imports = imports; - end_hide = imports.split("\n").length + 1; - // const range = new monaco.Range(1, 0, end_hide, 0); - // (editor as any).setHiddenAreas([range]); - } + const nmodel = monaco.editor.createModel( + val, + "typescript", + monaco.Uri.parse("file:///active.tsx") + ); + editor.setModel(nmodel); + const { exports, imports } = declareScope(p, meta, monaco); + console.log( + Object.keys(imports).map((e) => [ + p.page.meta[e].item.name, + exports[e], + ]) + ); + // const added = new Set(); + // const im = imports[active.item_id]; + // const im_flat = {} as Record; + // for (const [var_name, item] of Object.entries(im)) { + // const file_name = `${item.id}_${item.type}.tsx`; + // if (!im_flat[file_name]) im_flat[file_name] = []; + // im_flat[file_name].push(var_name); + // } + // console.log(im_flat, exports); + // if (active_src) { + // const end_hide = + // active_src.split("//!!start")[0].split("\n").length + 1; + // const range = new monaco.Range(1, 0, end_hide, 0); + // (editor as any).setHiddenAreas([range]); + // } } editor.trigger("fold", "editor.foldAllMarkerRegions", {}); await jsMount(editor, monaco, p); @@ -270,8 +264,8 @@ export const EdScriptMonaco: FC<{}> = () => { } onChange={(value) => { const stype = p.ui.popup.script.type; - if ((value || "").includes("/** IMPORT MODULE **/")) { - const valparts = (value || "").split("/** IMPORT MODULE **/\n"); + if ((value || "").includes("/** SOURCE START **/")) { + const valparts = (value || "").split("/** SOURCE START **/\n"); if (valparts.length === 2) local.value = valparts[1]; if ( stype === "prop-instance" && diff --git a/app/web/src/nova/ed/panel/popup/script/scope/add-scope.tsx b/app/web/src/nova/ed/panel/popup/script/scope/add-scope.tsx index cfd7c98e..a55c35ca 100644 --- a/app/web/src/nova/ed/panel/popup/script/scope/add-scope.tsx +++ b/app/web/src/nova/ed/panel/popup/script/scope/add-scope.tsx @@ -8,23 +8,21 @@ export const addScope = ( filename: string, source: string ) => { - const model = monaco.editor.getModels().find((e) => { - return e.uri.toString() === filename; - }); + // const model = monaco.editor.getModels().find((e) => { + // return e.uri.toString() === filename; + // }); - if (model) { - if (model.getValue() !== source) { - model.setValue(source); - } - } else { - const uri = monaco.Uri.parse(filename); - const model = monaco.editor.createModel(source, "typescript", uri); - - const arg = extractLoc(uri.path.split("_"), p); - model.onDidChangeContent((e) => { - // if (arg.id !== active.item_id && arg.type === "src") { - // console.log("changed", arg.id, e.changes); - // } - }); - } + // if (model) { + // return model; + // } else { + const uri = monaco.Uri.parse(filename); + const model = monaco.editor.createModel(source, "typescript", uri); + return model; + // const arg = extractLoc(uri.path.split("_"), p); + // model.onDidChangeContent((e) => { + // // if (arg.id !== active.item_id && arg.type === "src") { + // // console.log("changed", arg.id, e.changes); + // // } + // }); + // } }; diff --git a/app/web/src/nova/ed/panel/popup/script/scope/extract-export.tsx b/app/web/src/nova/ed/panel/popup/script/scope/extract-export.tsx index ca9908a9..9964f49b 100644 --- a/app/web/src/nova/ed/panel/popup/script/scope/extract-export.tsx +++ b/app/web/src/nova/ed/panel/popup/script/scope/extract-export.tsx @@ -4,7 +4,7 @@ export const extractExport = (p: PG, m: IMeta) => { const result = {} as Record< string, { - type: "local" | "passprop" | "prop"; + type: "local" | "passprop" | "prop" | "scope"; id: string; start: number; end: number; @@ -37,11 +37,11 @@ export const extractExport = (p: PG, m: IMeta) => { } } - if (m.script?.passprop) { - for (const [k, v] of Object.entries(m.script.passprop)) { + if (m.script?.scope) { + for (const [k, v] of Object.entries(m.script.scope)) { if (k === "key") continue; result[k] = { - type: "passprop", + type: "scope", id: m.item.id, start: 0, end: 0, diff --git a/app/web/src/nova/ed/panel/popup/script/scope/scope.tsx b/app/web/src/nova/ed/panel/popup/script/scope/scope.tsx index 223f72ab..9656eccb 100644 --- a/app/web/src/nova/ed/panel/popup/script/scope/scope.tsx +++ b/app/web/src/nova/ed/panel/popup/script/scope/scope.tsx @@ -1,7 +1,6 @@ import type { OnMount } from "@monaco-editor/react"; import { IContent } from "../../../../../../utils/types/general"; import { IMeta, PG, active } from "../../../../logic/ed-global"; -import { addScope } from "./add-scope"; import { extractExport } from "./extract-export"; type Monaco = Parameters[1]; @@ -16,177 +15,77 @@ export const declareScope = (p: PG, meta: IMeta, monaco: Monaco) => { : p.page.entry.map((e) => p.page.meta[e].item); const paths: IMeta[][] = []; + map_childs(monaco, p, metas, entry, paths); - const jsxprop_import_map: Record = {}; - map_childs( - monaco, - p, - metas, - entry, - paths, - active.comp_id ? [active.comp_id] : [], - jsxprop_import_map - ); - - let cur = active.comp_id ? active.comp_id : "page"; - const { import_map, parent_id } = extract_import_map( - cur, - paths, - meta, - p, - false, - monaco - ); - - const merged_import_map = { - ...import_map, - ...jsxprop_import_map, - }; - - gen_content(cur, p, paths, merged_import_map, monaco); - - if (cur !== "page" && !parent_id) { - return merged_import_map[paths[0][0].item.id]; - } - return merged_import_map[parent_id]; -}; - -const gen_content = ( - cur: string, - p: PG, - paths: IMeta[][], - import_map: Record, - monaco: Monaco -) => { - const added = new Set(); + const exports = {} as Record; + const extract_exports = {} as Record< + string, + ReturnType + >; + const imports = {} as Record< + string, + Record< + string, + { id: string; type: "prop" | "passprop" | "local" | "scope" } + > + >; + const cur_path = [] as IMeta[]; for (const path of paths) { - let idx = 0; - let last_import = cur !== "page" ? import_map[path[0].item.id] : ""; - - for (const m of path) { - if (!added.has(m.item.id) && m.item.adv?.js) { - added.add(m.item.id); - - const content = last_import - ? `\ -${last_import} -/** IMPORT MODULE **/ -${m.item.adv.js}` - : m.item.adv.js; - - addScope(p, monaco, `file:///${cur}_${m.item.id}_src_src.tsx`, content); - } - - if (!import_map[m.item.id]) { - if (idx === 0) { - break; + if (path.includes(meta)) { + for (const m of path) { + if (m.instances) { + cur_path.length = 0; } - } else { - last_import = import_map[m.item.id]; + cur_path.push(m); } - idx++; + break; } } -}; -const extract_import_map = ( - cur: string, - paths: IMeta[][], - meta: IMeta, - p: PG, - include_cur?: boolean, - monaco?: Monaco -) => { - const added = new Set(); - let parent_id = ""; - const import_map = {} as Record; - let cur_id = meta.item.id; + let prev_m = null as null | IMeta; + for (const m of cur_path) { + if (!exports[m.item.id]) { + const export_types = { + local: [] as string[], + prop: [] as string[], + passprop: [] as string[], + scope: [] as string[], + }; + extract_exports[m.item.id] = extractExport(p, m); - if (cur_id) { - for (const path of paths) { - const import_exists = {} as Record< - string, - { type: "prop" | "local" | "passprop"; str: string } - >; - - if ( - path - .map((e) => { - return e.item.id; - }) - .includes(cur_id) - ) { - let i = 0; - - let prev_m = null as any; - for (const m of path) { - if (m.item.id === cur_id) { - if (prev_m) parent_id = prev_m.item.id; - } - prev_m = m; - if (include_cur || (!include_cur && !added.has(m.item.id))) { - added.add(m.item.id); - - const ex = extractExport(p, m); - for (const [k, v] of Object.entries(ex)) { - let src = ""; - if (v.type === "local") { - src = `\ -const _local = ${v.val}; -export const ${k}: typeof _local & { render: ()=>void } = _local; -`; - } else { - src = `export const ${k} = ${v.val}`; - } - - if (src && monaco) { - addScope( - p, - monaco, - `file:///${cur}_${v.id}_${v.type}_${k}.tsx`, - `\ -${[...Object.values(import_exists).map((e) => e.str)].join("\n")} -/** IMPORT MODULE **/ -${src}` - ); - } - } - - for (const [k, v] of Object.entries(ex)) { - if ( - !include_cur && - m.item.id === cur_id && - ["local", "passprop"].includes(v.type) - ) { - continue; - } - - import_exists[k] = { - type: v.type, - str: `import { ${k} } from './${cur}_${v.id}_${v.type}_${k}';`, - }; - } - - import_map[m.item.id] = [ - ...Object.values(import_exists).map((e) => e.str), - ].join("\n"); - } - i++; + for (const [k, v] of Object.entries(extract_exports[m.item.id])) { + if (v.type !== "local") { + export_types[v.type].push(`export const ${k} = ${v.val};`); + } else { + export_types[v.type].push(`\ + const ${k}__local = ${v.val}; + export const ${k}: typeof ${k}__local & { render: ()=>void } = ${k}__local as any;`); + } + } + for (const [k, v] of Object.entries(export_types)) { + if (v.length > 0) { + exports[`${m.item.id}_${k}.tsx`] = v.join("\n"); } } } - } - return { import_map, parent_id }; -}; + if (prev_m && extract_exports[prev_m.item.id]) { + imports[m.item.id] = {}; + if (imports[prev_m.item.id]) { + for (const [k, v] of Object.entries(imports[prev_m.item.id])) { + imports[m.item.id][k] = v; + } + } -const comp_map = {} as Record< - string, - { - paths: IMeta[][]; - exports: Record>; + for (const [k, v] of Object.entries(extract_exports[prev_m.item.id])) { + imports[m.item.id][k] = { id: v.id, type: v.type }; + } + } + prev_m = m; } ->; + + return { exports, imports }; +}; const map_childs = ( monaco: Monaco, @@ -194,113 +93,44 @@ const map_childs = ( metas: Record, childs: IContent[], paths: IMeta[][], - skip_comp_id: string[], - jsxprop_import_map: Record = {}, curpath?: IMeta[] ) => { for (const m of childs) { const meta = metas[m.id]; if (meta) { paths.push([...(curpath || []), meta]); - // if ( - // meta.item.type === "item" && - // meta.item.component?.id && - // !skip_comp_id.includes(meta.item.component?.id) - // ) { - // const comp_id = meta.item.component.id; - // let jprop = comp_map[comp_id]; - // // if (!jprop) { - // // const comp_metas = p.comp.list[comp_id].meta; - // // comp_map[meta.item.component.id] = { - // // paths: [], - // // exports: {}, - // // }; - // // const id = p.comp.list[comp_id].doc - // // .getMap("map") - // // .get("root") - // // ?.get("id"); - - // // if (id) { - // // map_childs( - // // monaco, - // // p, - // // comp_metas, - // // [comp_metas[id].item], - // // comp_map[meta.item.component.id].paths, - // // [...skip_comp_id, comp_id] - // // ); - - // // jprop = comp_map[meta.item.component.id]; - // // for (const path of jprop.paths) { - // // for (const m of path) { - // // if (!jprop.exports[m.item.id]) { - // // jprop.exports[m.item.id] = extractExport(p, m); - // // } - // // } - // // } - // // } - // // } - - // if (jprop) { - // for (const [name, prop] of Object.entries( - // meta.item.component.props - // )) { - // if ( - // prop.meta?.type === "content-element" && - // prop.content && - // prop.jsxCalledBy - // ) { - // const m = metas[prop.jsxCalledBy[0]]; - // if (m && m.instances) { - // const instances = m.instances[prop.jsxCalledBy[0]]; - // if (instances) { - // const instance_id = instances[prop.jsxCalledBy[1]]; - // if (instance_id) { - // const mjsx = metas[instance_id]; - - // const { import_map, parent_id } = extract_import_map( - // "page", - // jprop.paths, - // mjsx, - // p, - // true, - // monaco - // ); - - // gen_content("page", p, jprop.paths, import_map, monaco); - - // jsxprop_import_map[prop.content.id] = import_map[parent_id]; - // const prop_meta = metas[prop.content.id]; - // map_childs( - // monaco, - // p, - // metas, - // prop.content.childs, - // paths, - // [...skip_comp_id, comp_id], - // jsxprop_import_map, - // [...(curpath || []), prop_meta] - // ); - // } - // } - // } - // } - // } - // } - // } else { - if (Array.isArray(meta.item.childs)) { - map_childs( - monaco, - p, - metas, - meta.item.childs, - paths, - [...skip_comp_id], - jsxprop_import_map, - [...(curpath || []), meta] - ); + if (meta.item.component?.id && meta.item.component?.props) { + for (const [name, prop] of Object.entries(meta.item.component.props)) { + if ( + prop.meta?.type === "content-element" && + prop.content && + prop.jsxCalledBy + ) { + const m = metas[prop.jsxCalledBy[0]]; + if (m && m.instances) { + const instances = m.instances[prop.jsxCalledBy[0]]; + if (instances) { + const instance_id = instances[prop.jsxCalledBy[1]]; + if (instance_id) { + const meta_parent = metas[instance_id]; + map_childs(monaco, p, metas, [prop.content], paths, [ + ...(curpath || []), + meta, + meta_parent, + ]); + } + } + } + } + } + } + + if (Array.isArray(meta.item.childs)) { + map_childs(monaco, p, metas, meta.item.childs, paths, [ + ...(curpath || []), + meta, + ]); } - // } } } }; diff --git a/app/web/src/nova/vi/render/script/eval-script.tsx b/app/web/src/nova/vi/render/script/eval-script.tsx index 7621f3c8..db7a837a 100644 --- a/app/web/src/nova/vi/render/script/eval-script.tsx +++ b/app/web/src/nova/vi/render/script/eval-script.tsx @@ -25,13 +25,13 @@ export const viEvalScript = ( if (!meta.script) { meta.script = { - passprop, + scope: passprop, result: null, Local: createViLocal(vi, meta), PassProp: createViPassProp(vi, meta), }; } else { - meta.script.passprop = passprop; + meta.script.scope = passprop; } const script = meta.script; diff --git a/app/web/src/nova/vi/render/script/local.tsx b/app/web/src/nova/vi/render/script/local.tsx index a04f97a8..26d71222 100644 --- a/app/web/src/nova/vi/render/script/local.tsx +++ b/app/web/src/nova/vi/render/script/local.tsx @@ -27,7 +27,7 @@ export const createViLocal = ( const local = ref.current; local.render = meta.render; - updatePropScope(vi, meta, meta.script?.passprop); + updatePropScope(vi, meta, meta.script?.scope); if (arg.hook) { arg.hook(local); @@ -67,7 +67,7 @@ export const createViLocal = ( }, []); return modifyChild(children, { - ...meta.script?.passprop, + ...meta.script?.scope, [arg.name]: local, }); }; diff --git a/app/web/src/nova/vi/render/script/passprop.tsx b/app/web/src/nova/vi/render/script/passprop.tsx index 48860c87..8492a668 100644 --- a/app/web/src/nova/vi/render/script/passprop.tsx +++ b/app/web/src/nova/vi/render/script/passprop.tsx @@ -4,7 +4,23 @@ import { VG } from "../global"; export const createViPassProp = (vi: { meta: VG["meta"] }, meta: IMeta) => { return (arg: Record & { children: ReactNode }) => { - return modifyChild(arg, meta.script?.passprop); + if (!meta.item.script) { + meta.item.script = {}; + } + + if (!meta.item.script.passprop) { + meta.item.script.passprop = {}; + } + + if (meta.item.script.passprop) { + for (const [k, v] of Object.entries(arg)) { + if (!["children", "key"].includes(k)) { + meta.item.script.passprop[k] = { end: 0, start: 0, value: v }; + } + } + } + + return modifyChild(arg, meta.script?.scope); }; }; diff --git a/app/web/src/nova/vi/utils/types.ts b/app/web/src/nova/vi/utils/types.ts index d88277f4..c8a3b5e0 100644 --- a/app/web/src/nova/vi/utils/types.ts +++ b/app/web/src/nova/vi/utils/types.ts @@ -59,7 +59,7 @@ export type IMeta = { is_root: boolean; }; script?: { - passprop?: any; + scope?: any; result: ReactNode; Local: ReturnType; PassProp: ReturnType;