This commit is contained in:
Rizky 2023-12-10 15:45:16 +07:00
parent 0ca6a56eb6
commit 209d26ac9a
10 changed files with 420 additions and 17 deletions

View File

@ -51,6 +51,7 @@ export const ScriptMonaco = () => {
(async () => {
const editor = local.editor;
const monaco = local.monaco;
if (monaco && editor) {
if (!local.init) {
if (p.ui.popup.script.mode === "js") {
@ -87,9 +88,11 @@ export const ScriptMonaco = () => {
monaco,
{ types: {}, values: {} }
);
declareScope(p, editor, monaco).then(() => {
local.render();
});
if (meta) {
declareScope(p, meta, editor, monaco).then(() => {
local.render();
});
}
}
local.init = true;

View File

@ -1,26 +1,48 @@
import type { OnMount } from "@monaco-editor/react";
import { deepClone } from "web-utils";
import { EPage, ISingleScope, PG, active } from "../../../logic/ed-global";
import {
EPage,
EdMeta,
ISingleScope,
PG,
active,
} from "../../../logic/ed-global";
import { getMetaById } from "../../../logic/tree/build";
type Monaco = Parameters<OnMount>[1];
export type MonacoEditor = Parameters<OnMount>[0];
export const declareScope = async (
p: PG,
meta: EdMeta,
editor: MonacoEditor,
monaco: Monaco
) => {
let active_id = active.item_id;
let s = deepClone(p.page.scope[active_id]);
if (active.comp_id && p.comp.list[active.comp_id]) {
s = deepClone(p.comp.list[active.comp_id].scope[active.item_id]);
const root = active.comp_id
? p.comp.list[active.comp_id].scope
: p.page.scope;
const meta_root = active.comp_id
? p.comp.list[active.comp_id].meta
: p.page.meta;
if (!root) return;
let cur = meta;
while (!root[cur.item.id]) {
const parent = meta_root[cur.parent_item.id];
if (parent) {
cur = parent;
} else {
break;
}
}
const s = root[cur.item.id];
if (!s) return;
s.p.push(active_id);
const existing: Record<string, IEachArgScope> = {};
spreadScope(p, s, (arg) => {
@ -50,10 +72,10 @@ export const declareScope = async (
arg.type
}~${arg.name}~${arg.id}`,
`\
export const {};
declare global {
const ${arg.name} = ${arg.value};
}`
export const {};
declare global {
const ${arg.name} = ${arg.value};
}`
);
} else {
addScope(
@ -62,11 +84,11 @@ declare global {
arg.type
}~${arg.id}`,
`\
export const {};
const __val = ${arg.value};
declare global {
const ${arg.name}: typeof __val & { render: ()=>void };
}`
export const {};
const __val = ${arg.value};
declare global {
const ${arg.name}: typeof __val & { render: ()=>void };
}`
);
}
});

View File

@ -0,0 +1,117 @@
import { MItem } from "../../../../utils/types/item";
import { evalPropVis } from "./comp/eval-prop-vis";
import { instantiate } from "./comp/instantiate";
import { walkProp } from "./comp/walk-prop";
import { genMeta } from "./meta";
import { applyRefIds } from "./ref-ids";
import { simplify } from "./simplify";
import { GenMetaArg, GenMetaP, IMeta } from "./types";
export const genComp = (
p: GenMetaP,
arg: GenMetaArg,
r: ReturnType<typeof applyRefIds>
) => {
const { item } = arg;
const mitem = arg.mitem as MItem;
if (item.type === "item" && item.component?.id && arg.parent?.item.id) {
let pcomp = p.comps[item.component.id];
if (!pcomp && p.on.load_component) {
p.on.load_component(item.component.id);
return;
}
if (pcomp) {
const ref_ids = r?.ref_ids || item.component?.ref_ids || {};
let mref_ids = r?.mref_ids || mitem.get("component")?.get("ref_ids");
if (!mref_ids && mitem) {
mitem.get("component")?.set("ref_ids", new Y.Map() as any);
mref_ids = mitem.get("component")?.get("ref_ids");
}
instantiate(item, pcomp.comp, ref_ids, mref_ids);
const meta: IMeta = {
item: simplify(item),
parent: {
id: arg.parent.item.id,
instance_id: arg.parent?.instance?.id,
comp_id: arg.parent?.comp?.id,
},
scope: {
def: {
props: {},
},
},
};
const props = {} as Record<string, { value: any; visible?: string }>;
walkProp({
item,
mitem: mitem,
pcomp,
each(name, prop, mprop) {
if (meta.scope.def?.props) {
meta.scope.def.props[name] = {
value: prop.valueBuilt,
visible: true,
};
}
props[name] = { value: prop.valueBuilt, visible: prop.visible };
if (prop.meta?.type === "content-element" && prop.content) {
genMeta(p, {
item: prop.content,
mitem: mprop?.get("content"),
is_root: false,
jsx_prop: {
is_root: true,
name,
},
parent: {
item,
mitem: mitem,
comp: pcomp.comp,
mcomp: pcomp.mcomp,
instance: arg.parent?.instance || item,
minstance: arg.parent?.minstance || mitem,
},
});
}
},
});
const vis = evalPropVis(props);
if (vis && meta.scope.def?.props) {
for (const [k, v] of Object.entries(vis)) {
if (meta.scope.def.props[k]) {
meta.scope.def.props[k].visible = !!v;
}
}
}
p.meta[item.id] = meta;
if (p.on.visit) {
p.on.visit(meta);
}
for (const [k, v] of Object.entries(item.childs)) {
const mchild = mitem.get("childs")?.get(k as unknown as number);
genMeta(p, {
item: v,
mitem: mchild,
is_root: false,
parent: {
item,
mitem: mitem,
comp: pcomp.comp,
mcomp: pcomp.mcomp,
instance: arg.parent?.instance || item,
minstance: arg.parent?.minstance || mitem,
},
});
}
}
}
};

View File

@ -0,0 +1,20 @@
export const evalPropVis = (
props: Record<string, { value: string; visible?: string }>
) => {
try {
const fn = new Function(`
${Object.entries(props)
.map(([k, v]) => `const ${k} = ${v.value};`)
.join("\n")}
return {
${Object.entries(props)
.filter(([k, v]) => v.visible)
.map(([k, v]) => `${k}: ${v},`)
.join("\n")}
}
`);
return fn() as Record<string, boolean>;
} catch (e) {}
};

View File

@ -0,0 +1,40 @@
import { TypedMap } from "yjs-types";
import { IItem } from "../../../../../utils/types/item";
import { applyRefIds } from "../ref-ids";
import { createId } from "@paralleldrive/cuid2";
export const instantiate = (
item: IItem,
comp: IItem,
ref_ids: Record<string, string>,
mref_ids?: Record<string, string> & TypedMap<Record<string, string>>
) => {
const newitem = structuredClone(comp);
if (item.id) {
newitem.id = item.id;
}
if (item.component) {
newitem.component = item.component;
}
walkChild(newitem, ref_ids, mref_ids);
};
const walkChild = (
item: IItem,
ref_ids: Record<string, string>,
mref_ids?: Record<string, string> & TypedMap<Record<string, string>>
) => {
if (!ref_ids[item.id]) {
ref_ids[item.id] = createId();
mref_ids?.set(item.id, ref_ids[item.id]);
}
item.id = ref_ids[item.id];
if (item.childs) {
for (const child of item.childs) {
walkChild(item, ref_ids, mref_ids);
}
}
};

View File

@ -0,0 +1,32 @@
import { IItem, MItem } from "../../../../../utils/types/item";
import { FMCompDef, FNCompDef } from "../../../../../utils/types/meta-fn";
export const walkProp = (arg: {
item: IItem;
mitem?: MItem;
pcomp: { comp: IItem; mcomp?: MItem };
each: (name: string, prop: FNCompDef, mprop?: FMCompDef) => void;
}) => {
for (const [k, v] of Object.entries(arg.pcomp.comp.component?.props || {})) {
let mprop = arg.mitem?.get("component")?.get("props")?.get(k);
if (!mprop) {
const map = new Y.Map() as any;
syncronize(map, v);
arg.mitem?.get("component")?.get("props")?.set(k, map);
mprop = arg.mitem?.get("component")?.get("props")?.get(k);
}
const props = arg.item.component?.props;
let prop = props?.[k];
if (props) {
if (!props[k]) {
props[k] = v;
prop = v;
}
}
if (prop) {
arg.each(k, prop, mprop);
}
}
};

View File

@ -0,0 +1,65 @@
import { IItem, MItem } from "../../../../utils/types/item";
import { genComp } from "./comp";
import { applyRefIds } from "./ref-ids";
import { simplify } from "./simplify";
import { GenMetaArg, GenMetaP, IMeta } from "./types";
export const genMeta = (p: GenMetaP, arg: GenMetaArg) => {
let wrapper = (fn: any) => {
fn();
};
if (arg.is_root && arg.mitem) {
const transact = arg.mitem.doc?.transact;
if (transact) {
wrapper = transact;
}
}
wrapper(() => {
const { parent } = arg;
const item = arg.item as IItem;
const mitem = arg.mitem as MItem;
const r = applyRefIds(item, mitem, parent);
if (item.type === "item" && item.component?.id) {
genComp(p, arg, r);
return;
}
const meta: IMeta = {
item: simplify(item),
parent: {
id: arg.parent?.item.id || "root",
instance_id: arg.parent?.instance?.id,
comp_id: arg.parent?.comp?.id,
},
scope: {},
};
if (p.on.visit) {
p.on.visit(meta);
}
p.meta[item.id] = meta;
if (item.childs) {
for (const [k, v] of Object.entries(item.childs)) {
const mchild = mitem.get("childs")?.get(k as unknown as number);
genMeta(p, {
item: v,
mitem: mchild,
is_root: false,
parent: {
item,
mitem: mitem,
comp: arg.parent?.comp,
mcomp: arg.parent?.mcomp,
instance: arg.parent?.instance,
minstance: arg.parent?.minstance,
},
});
}
}
});
};

View File

@ -0,0 +1,34 @@
import { createId } from "@paralleldrive/cuid2";
import { IContent, MContent } from "../../../../utils/types/general";
import { IItem } from "../../../../utils/types/item";
export const applyRefIds = (
item: IContent,
mitem?: MContent,
parent?: { instance?: IItem; minstance?: MContent }
) => {
const instance = parent?.instance;
if (instance && instance.component) {
let mref_ids = parent?.minstance?.get("component")?.get("ref_ids");
if (!mref_ids) {
mref_ids = new Y.Map() as any;
}
if (mref_ids) parent?.minstance?.get("component")?.set("ref_ids", mref_ids);
const ref_ids = instance.component.ref_ids || {};
if (!ref_ids[item.id]) {
ref_ids[item.id] = createId();
mref_ids?.set(item.id, ref_ids[item.id]);
}
if (ref_ids[item.id]) {
if (!item.originalId) item.originalId = item.id;
item.id = ref_ids[item.id];
mitem?.set("id", item.id);
}
return { ref_ids, mref_ids };
}
};

View File

@ -0,0 +1,18 @@
import { IItem } from "../../../../utils/types/item";
export const simplify = (item: IItem) => {
const newitem = {} as any;
for (const [k, v] of Object.entries(item)) {
if (k === "childs") {
newitem.childs = [];
if (v && Array.isArray(v)) {
for (const child of v) {
newitem.childs.push({ id: child.id });
}
}
} else {
newitem[k] = v;
}
}
return newitem as IItem;
};

View File

@ -0,0 +1,52 @@
import { IContent, MContent } from "../../../../utils/types/general";
import { IItem, MItem } from "../../../../utils/types/item";
export type GenMetaP = {
meta: Record<string, IMeta>;
comps: Record<string, { comp: IItem; mcomp?: MItem }>;
on: {
load_component?: (id: string) => Promise<{ item: IItem; mcomp?: MItem }>;
visit?: (meta: IMeta) => void;
};
};
export type GenMetaArg = {
item: IContent;
is_root?: boolean;
mitem?: MContent;
jsx_prop?: IMeta["jsx_prop"];
parent?: {
item: IItem;
mitem?: MItem;
comp?: IItem;
mcomp?: MItem;
instance?: IItem;
minstance?: MItem;
};
};
export type IMeta = {
item: IItem;
parent?: {
id: string;
instance_id?: string;
comp_id?: string;
};
jsx_prop?: {
name: string;
is_root: boolean;
};
scope: {
val?: any;
def?: {
props?: Record<string, { value: string; visible: boolean }>;
local?: {
name: string;
idx: number;
idxval: Record<string, number>;
src: string;
};
pass?: Record<string, { src: string; idx: number }>;
};
};
};