import type { OnMount } from "@monaco-editor/react"; import trim from "lodash.trim"; import { MonacoJsxSyntaxHighlight, getWorker, } from "monaco-jsx-syntax-highlight-v2"; import { PG, active } from "../../nova/ed/logic/ed-global"; import { jscript } from "./jscript"; export type MonacoEditor = Parameters[0]; type Monaco = Parameters[1]; type CompilerOptions = Parameters< Parameters[1]["languages"]["typescript"]["typescriptDefaults"]["setCompilerOptions"] >[0]; export const jsMount = async (editor: MonacoEditor, monaco: Monaco, p?: PG) => { const m = monaco as any; if (editor.getModel()) { const jsxHgController = new MonacoJsxSyntaxHighlight(getWorker(), monaco); const { highlighter } = jsxHgController.highlighterBuilder({ editor: editor, }); if (typeof editor.getModel === "function") { highlighter(); } editor.onDidChangeModelContent(() => { if (typeof editor.getModel === "function") { try { highlighter(); } catch (e) {} } }); } if (!m.customJSMounted) { m.customJSMounted = true; } else { return; } const compilerOptions: CompilerOptions = { jsx: monaco.languages.typescript.JsxEmit.React, jsxFactory: "React.createElement", jsxFragmentFactory: "React.Fragment", target: monaco.languages.typescript.ScriptTarget.ES2015, allowNonTsExtensions: true, lib: ["esnext", "dom"], module: monaco.languages.typescript.ModuleKind.ESNext, esModuleInterop: true, moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs, }; if (p) { monaco.editor.registerEditorOpener({ openCodeEditor(source, r, selectionOrPosition) { if (p) { p.ui.popup.script.mode === "js"; const cpath = r.path.substring(`scope~`.length).split("__").pop() || ""; let arg = { type: "" as "prop" | "item", item_id: "" as string | undefined, comp_id: "", prop_name: "", }; try { arg = JSON.parse(cpath.substring(0, cpath.length - 5) || "{}"); } catch (e) {} if (arg.type) { if (arg.type === "item") { p.ui.popup.script.open = false; p.ui.popup.script.type = "item"; p.ui.popup.script.prop_name = ""; p.render(); } else { p.ui.popup.script.open = false; p.render(); } setTimeout(() => { p.ui.popup.script.open = true; if (arg.type === "item") { if (arg.item_id) { active.item_id = arg.item_id; p.render(); } } else if (arg.type === "prop") { active.comp_id = arg.comp_id; p.ui.popup.script.prop_name = arg.prop_name; p.ui.popup.script.type = "prop-instance"; p.ui.popup.script.prop_kind = "value"; p.ui.popup.script.open = true; p.render(); } }, 100); } // const [comp_id, prev_comp_id, prev_item_id] = cpath[0].split("~"); // if (cpath[1]) { // const path = cpath[1].split("~"); // const type = path[0] as "prop" | "passprop" | "local"; // const id = path[path.length - 1].replace(".d.ts", ""); // if (type === "prop") { // p.ui.popup.script.open = false; // p.render(); // setTimeout(() => { // p.ui.popup.script.type = "item"; // p.ui.popup.script.prop_name = path[1]; // p.ui.popup.script.type = "prop-instance"; // p.ui.popup.script.prop_kind = "value"; // p.ui.popup.script.open = true; // if ( // !prev_comp_id && // !prev_item_id && // active.instance.item_id && // active.comp_id // ) { // active.item_id = active.instance.item_id; // active.comp_id = active.instance.comp_id; // active.instance.item_id = ""; // active.instance.comp_id = ""; // } // p.render(); // }, 100); // return false; // } else { // p.ui.popup.script.open = false; // p.ui.popup.script.type = "item"; // p.ui.popup.script.prop_name = ""; // p.render(); // setTimeout(() => { // if (comp_id) { // let meta = p.page.meta[id]; // if (active.comp_id) { // meta = p.comp.list[active.comp_id].meta[id]; // return false; // } // active.instance.comp_id = active.comp_id; // active.instance.item_id = active.item_id; // if (meta && meta.item.originalId) { // active.item_id = meta.item.originalId; // } else { // active.item_id = id; // } // active.comp_id = comp_id; // } else { // if (active.comp_id) { // let meta = p.comp.list[active.comp_id].meta[id]; // if (!meta) { // const _id = p.comp.list[active.comp_id].doc // .getMap("map") // .get("root") // ?.get("id"); // if (_id) { // active.item_id = _id; // p.render(); // } // } // return false; // } // active.item_id = id; // } // p.ui.popup.script.open = true; // p.render(); // }, 100); // } // } } return false; }, }); } monaco.languages.registerDocumentFormattingEditProvider("typescript", { async provideDocumentFormattingEdits(model, options, token) { const prettier = jscript.prettier.standalone; const prettier_ts = jscript.prettier.ts; const prettier_estree = jscript.prettier.estree; if (prettier && prettier_estree && prettier_ts) { const text = trim( await prettier.format(model.getValue(), { parser: "typescript", plugins: [prettier_ts, prettier_estree], }), "; \n" ); return [ { range: model.getFullModelRange(), text, }, ]; } }, }); monaco.languages.registerCompletionItemProvider("typescript", { provideCompletionItems: (model, position) => { const word = model.getWordUntilPosition(position); return { suggestions: [ { label: "log", kind: monaco.languages.CompletionItemKind.Snippet, documentation: "Add Console.log", insertText: `console.log($1)`, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, range: { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn, endColumn: word.endColumn, }, }, { label: "sfy", kind: monaco.languages.CompletionItemKind.Snippet, documentation: "Add JSON.stringify", insertText: `JSON.stringify($1)`, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, range: { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn, endColumn: word.endColumn, }, }, ], }; }, }); monaco.languages.registerCompletionItemProvider("typescript", { triggerCharacters: [">"], provideCompletionItems: (model, position) => { const codePre: string = model.getValueInRange({ startLineNumber: position.lineNumber, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column, }); const tag = codePre.match(/.*<(\w+)>$/)?.[1]; if (!tag) { return; } const word = model.getWordUntilPosition(position); return { suggestions: [ { label: ``, kind: monaco.languages.CompletionItemKind.EnumMember, insertText: `$1`, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, range: { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn, endColumn: word.endColumn, }, }, ], }; }, }); monaco.languages.typescript.typescriptDefaults.setCompilerOptions( compilerOptions ); setTimeout(() => { editor.getAction("editor.action.formatDocument")?.run(); }, 100); };