diff --git a/app/srv/package.json b/app/srv/package.json index e58a57d8..7979c789 100644 --- a/app/srv/package.json +++ b/app/srv/package.json @@ -8,6 +8,8 @@ "@paralleldrive/cuid2": "^2.2.2", "@types/mime-types": "^2.1.2", "esbuild": "^0.19.4", + "@swc/core": "^1.3.96", + "woodpile": "^0.0.5", "lmdb": "^2.8.5", "mime-types": "^2.1.35", "msgpackr": "^1.9.9", diff --git a/app/srv/ws/sync/actions.ts b/app/srv/ws/sync/actions.ts index f21ce52a..d32dd23b 100644 --- a/app/srv/ws/sync/actions.ts +++ b/app/srv/ws/sync/actions.ts @@ -1,9 +1,5 @@ import { component, page } from "dbgen"; -import { - EComp, - EPage, - ESite, -} from "../../../web/src/nova/ed/logic/ed-global"; +import { EComp, EPage, ESite } from "../../../web/src/nova/ed/logic/ed-global"; import { IItem } from "../../../web/src/utils/types/item"; import { site_group } from "./actions/site_group"; import { activity } from "./entity/activity"; @@ -92,4 +88,11 @@ export const SyncActions = { info: async (client_ids: string[]) => ({}) as Record, }, + swc: { + parse: async ( + arg: + | { page_id: string; item_id?: string } + | { comp_id: string; item_id?: string } + ) => ({}) as Record, + }, }; diff --git a/app/web/package.json b/app/web/package.json index 9170137d..0f61d16a 100644 --- a/app/web/package.json +++ b/app/web/package.json @@ -15,7 +15,6 @@ "@parcel/packager-wasm": "^2.10.1", "@parcel/service-worker": "^2.10.1", "@qiwi/deep-proxy": "^2.0.3", - "@swc/wasm-web": "1.3.96-nightly-20231025.1", "algoliasearch": "^4.20.0", "date-fns": "^2.30.0", "dbgen": "workspace:*", diff --git a/app/web/src/nova/ed/logic/ed-global.ts b/app/web/src/nova/ed/logic/ed-global.ts index 5bbdfdc4..6e3f0cb6 100644 --- a/app/web/src/nova/ed/logic/ed-global.ts +++ b/app/web/src/nova/ed/logic/ed-global.ts @@ -88,6 +88,7 @@ export const EDGlobal = { | "ready", sync: null as unknown as Awaited>, site: deepClone(EmptySite), + site_dts: "", script: { siteTypes: {} as Record, loaded: false, 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 84807f40..0b8d7846 100644 --- a/app/web/src/nova/ed/panel/popup/script/monaco.tsx +++ b/app/web/src/nova/ed/panel/popup/script/monaco.tsx @@ -1,13 +1,84 @@ -import type { Editor as MonacoEditor, OnMount } from "@monaco-editor/react"; +import type { OnMount } from "@monaco-editor/react"; +import { createStore } from "idb-keyval"; +import trim from "lodash.trim"; +import { useEffect } from "react"; +import { useGlobal, useLocal } from "web-utils"; import { jscript } from "../../../../../utils/script/jscript"; +import { EDGlobal, active } from "../../../logic/ed-global"; +import { jsMount } from "../../../../../utils/script/mount"; +import { monacoTypings } from "../../../../../utils/script/typings"; export type MonacoEditor = Parameters[0]; export const ScriptMonaco = () => { + const p = useGlobal(EDGlobal, "EDITOR"); + const local = useLocal({ + editor: null as null | MonacoEditor, + reloading: false, + changeTimeout: 0 as any, + historyOpen: false, + idbstore: createStore(`prasi-page-${p.page.cur.id}`, "script-history"), + }); + const Editor = jscript.editor; if (!Editor) return null; + const meta = p.page.meta[active.item_id]; + if (!meta) return null; + + const item = meta.item; + const adv = item.adv || {}; + const val: string = ( + typeof adv[p.ui.popup.script.mode] === "string" + ? adv[p.ui.popup.script.mode] + : "" + ) as any; + + const doEdit = async (newval: string, all?: boolean) => { + if (local.editor && jscript.prettier.standalone) { + const text = trim( + await jscript.prettier.standalone.format( + all + ? newval + : local.editor?.getValue().replace(/\{\s*children\s*\}/gi, newval) + ), + "; \n" + ); + + local.editor.executeEdits(null, [ + { + range: { + startLineNumber: 0, + startColumn: 0, + endColumn: Number.MAX_SAFE_INTEGER, + endLineNumber: Number.MAX_SAFE_INTEGER, + }, + text, + }, + ]); + } + }; + + let mitem = meta.mitem; + + if (!mitem) { + active.item_id = ""; + return
no mitem
; + } else if ( + item.type === "item" && + item.component?.id && + meta.parent_comp?.mitem + ) { + mitem = meta.parent_comp?.mitem; + + if (!mitem) { + active.item_id = ""; + return
no mitem
; + } + } + return ( { tabSize: 2, useTabStops: true, }} + onMount={async (editor, monaco) => { + local.editor = editor; + editor.focus(); + setTimeout(() => { + editor.focus(); + }, 300); + + const value = editor.getValue(); + if (p.ui.popup.script.mode === "js") { + monaco.editor.getModels().forEach((model) => { + if (model.uri.toString().startsWith("inmemory://model")) { + model.dispose(); + } + }); + + let model = monaco.editor.createModel( + value, + "typescript", + monaco.Uri.parse( + `ts:${ + p.comp.cur.id + ? `comp-${p.comp.cur.id}` + : `page-${p.page.cur.id}` + }-${active.item_id}.tsx` + ) + ); + editor.setModel(model); + } + monaco.editor.registerEditorOpener({ + openCodeEditor(source, resource, selectionOrPosition) { + // https://github.com/microsoft/vscode/pull/177064#issue-1623100628 + console.log(source, resource, selectionOrPosition); + return false; + }, + }); + + await jsMount(editor, monaco); + await monacoTypings( + { + site_dts: p.site_dts, + script: { + siteTypes: {}, + }, + site: p.site.config, + }, + monaco, + { types: {}, values: {} } + ); + }} /> ); }; diff --git a/app/web/src/nova/ed/panel/popup/script/workbench.tsx b/app/web/src/nova/ed/panel/popup/script/workbench.tsx index 2a8d807d..914e0635 100644 --- a/app/web/src/nova/ed/panel/popup/script/workbench.tsx +++ b/app/web/src/nova/ed/panel/popup/script/workbench.tsx @@ -15,6 +15,7 @@ export const ScriptWorkbench = () => { ].map((e) => { return (
+
- {""} +
`, + }} + >
); diff --git a/bun.lockb b/bun.lockb index 67ed468a..74ee5f56 100755 Binary files a/bun.lockb and b/bun.lockb differ