(function () { const VS_BASE = "/_content/ZB.MOM.WW.OtOpcUa.AdminUI/lib/monaco/vs"; const editors = {}; let readyPromise = null; function ensureLoaded() { if (readyPromise) return readyPromise; readyPromise = new Promise(function (resolve, reject) { const loader = document.createElement("script"); loader.src = VS_BASE + "/loader.js"; loader.onload = function () { require.config({ paths: { vs: VS_BASE } }); require(["vs/editor/editor.main"], function () { registerCSharpProviders(); resolve(); }); }; loader.onerror = function (e) { reject(e); }; document.head.appendChild(loader); }); return readyPromise; } const KIND_MAP = { Method: 0, Field: 4, Property: 9, Event: 10, Class: 6, Module: 8, Variable: 4, Text: 18 }; function registerCSharpProviders() { monaco.languages.registerCompletionItemProvider("csharp", { triggerCharacters: [".", "(", "\""], provideCompletionItems: async function (model, position) { try { const resp = await fetch("/api/script-analysis/completions", { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ codeText: model.getValue(), line: position.lineNumber, column: position.column }) }); if (!resp.ok) return { suggestions: [] }; const data = await resp.json(); const word = model.getWordUntilPosition(position); const range = { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn, endColumn: word.endColumn }; return { suggestions: (data.items || []).map(function (it) { return { label: it.label, insertText: it.insertText, detail: it.detail, kind: KIND_MAP[it.kind] != null ? KIND_MAP[it.kind] : 18, range: range }; }) }; } catch (e) { return { suggestions: [] }; } } }); monaco.languages.registerHoverProvider("csharp", { provideHover: async function (model, position) { try { const resp = await fetch("/api/script-analysis/hover", { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ codeText: model.getValue(), line: position.lineNumber, column: position.column }) }); if (!resp.ok) return null; const data = await resp.json(); if (!data.markdown) return null; return { contents: [{ value: data.markdown }] }; } catch (e) { return null; } } }); monaco.languages.registerDocumentFormattingEditProvider("csharp", { provideDocumentFormattingEdits: async function (model) { try { const resp = await fetch("/api/script-analysis/format", { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ code: model.getValue() }) }); if (!resp.ok) return []; const data = await resp.json(); if (typeof data.code !== "string" || data.code === model.getValue()) return []; return [{ range: model.getFullModelRange(), text: data.code }]; } catch (e) { return []; } } }); monaco.languages.registerInlayHintsProvider("csharp", { provideInlayHints: async function (model) { try { const resp = await fetch("/api/script-analysis/inlay-hints", { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ code: model.getValue() }) }); if (!resp.ok) return { hints: [], dispose: function () {} }; const data = await resp.json(); return { hints: (data.hints || []).map(function (h) { return { position: { lineNumber: h.line, column: h.column }, label: h.label, kind: 2, paddingRight: true }; }), dispose: function () {} }; } catch (e) { return { hints: [], dispose: function () {} }; } } }); monaco.languages.registerSignatureHelpProvider("csharp", { signatureHelpTriggerCharacters: ["(", ","], signatureHelpRetriggerCharacters: [","], provideSignatureHelp: async function (model, position) { try { const resp = await fetch("/api/script-analysis/signature-help", { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ codeText: model.getValue(), line: position.lineNumber, column: position.column }) }); if (!resp.ok) return null; const data = await resp.json(); if (!data.label) return null; return { value: { signatures: [{ label: data.label, parameters: (data.parameters || []).map(function (p) { return { label: p.label, documentation: p.documentation }; }) }], activeSignature: 0, activeParameter: data.activeParameter || 0 }, dispose: function () {} }; } catch (e) { return null; } } }); } async function fetchDiagnostics(model) { try { const resp = await fetch("/api/script-analysis/diagnostics", { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ code: model.getValue() }) }); if (!resp.ok) return []; const data = await resp.json(); return data.markers || []; } catch (e) { return []; } } async function createEditor(id, host, options, dotNetRef) { await ensureLoaded(); if (!host) return; const editor = monaco.editor.create(host, { value: options.value || "", language: options.language || "csharp", theme: "vs", minimap: { enabled: false }, scrollBeyondLastLine: false, automaticLayout: true, fontSize: 13, lineNumbers: "on", renderLineHighlight: "line", readOnly: !!options.readOnly, tabSize: 4, insertSpaces: true, wordWrap: "off", fixedOverflowWidgets: true }); let diagTimer = null; const scheduleDiagnostics = function () { if (diagTimer) clearTimeout(diagTimer); diagTimer = setTimeout(async function () { const model = editor.getModel(); if (!model) return; const markers = await fetchDiagnostics(model); monaco.editor.setModelMarkers(model, "otopcua", markers); dotNetRef.invokeMethodAsync("OnMarkersChanged", markers).catch(function () {}); }, 500); }; editor.onDidChangeModelContent(function () { dotNetRef.invokeMethodAsync("OnValueChanged", editor.getValue()).catch(function () {}); if (options.language === "csharp") scheduleDiagnostics(); }); editors[id] = { editor: editor, dotNetRef: dotNetRef }; if (options.language === "csharp") scheduleDiagnostics(); } function setEditorOption(id, name, value) { const e = editors[id]; if (!e) return; // Note: monaco.editor.setTheme is global — it re-themes every editor on the page, not just this id. if (name === "theme") { monaco.editor.setTheme(value); return; } const u = {}; u[name] = value; e.editor.updateOptions(u); } function format(id) { editors[id]?.editor.getAction("editor.action.formatDocument")?.run(); } function revealLine(id, line, col) { const e = editors[id]; if (!e) return; e.editor.revealLineInCenter(line); e.editor.setPosition({ lineNumber: line, column: col || 1 }); e.editor.focus(); } function setValue(id, v) { const e = editors[id]; if (e && e.editor.getValue() !== v) e.editor.setValue(v || ""); } function getValue(id) { const e = editors[id]; return e ? e.editor.getValue() : null; } function setMarkers(id, m) { const e = editors[id]; const model = e && e.editor.getModel(); if (model) monaco.editor.setModelMarkers(model, "otopcua", m || []); } function dispose(id) { const e = editors[id]; if (!e) return; try { e.editor.dispose(); } catch (x) {} delete editors[id]; } window.MonacoBlazor = { createEditor, setValue, getValue, setMarkers, setEditorOption, format, revealLine, dispose }; })();