Skip to main content
Glama

Memory Bank MCP Server

by t3ta
editor.js10.3 kB
// @ts-check /** * editor.js - Memory Bank Document Editor WebView Script * This script handles the interactive behavior of the Memory Bank document editor webview. */ /* eslint-env browser */ /* global acquireVsCodeApi, mermaid */ (function () { const vscode = acquireVsCodeApi(); let editor, previewContentDiv, errorMessageDiv; let lastKnownText = ''; /** * Initialize the editor functionality. */ function initialize() { console.log('[Webview] Initializing editor script...'); // Add log at the start // Get DOM elements editor = document.getElementById('editor'); previewContentDiv = document.getElementById('preview-content'); errorMessageDiv = document.getElementById('error-message'); if (editor) { lastKnownText = editor.value; // Setup event listeners for editor changes editor.addEventListener('input', handleEditorInput); } else { console.error('[Webview] Editor element not found'); } // Handle messages from the extension window.addEventListener('message', handleExtensionMessages); // Setup mode toggle buttons setupModeToggle(); console.log('[Webview] Script loaded and listeners attached.'); // Initialize Mermaid if available initializeMermaid(); // Request initial preview requestInitialPreview(); // Attempt initial Mermaid rendering after a delay setTimeout(attemptInitialMermaidRender, 150); console.log('[Webview] Editor script initialization complete.'); } /** * Initialize Mermaid library if available */ function initializeMermaid() { try { if (typeof mermaid !== 'undefined') { console.log('[Webview] Mermaid library found, initializing...'); // Initialize with default config mermaid.initialize({ startOnLoad: false, // We'll manually run rendering theme: 'default', securityLevel: 'loose', // Needed for webview rendering flowchart: { useMaxWidth: true, htmlLabels: true }, logLevel: 3, // Error }); console.log('[Webview] Mermaid initialized successfully'); return true; } else { console.warn('[Webview] Mermaid library not found during initialization.'); return false; } } catch (err) { console.error('[Webview] Error initializing Mermaid:', err); return false; } } /** * Request the initial preview from the extension */ function requestInitialPreview() { console.log("[Webview] Sending 'requestPreview' message to extension."); vscode.postMessage({ type: 'requestPreview', payload: lastKnownText }); } /** * Handle input events from the editor textarea * @param {Event} e - The input event */ function handleEditorInput(e) { const newText = e.target.value; lastKnownText = newText; errorMessageDiv.textContent = ''; // Basic JSON validation try { JSON.parse(newText); // Send update to extension host for processing and preview generation vscode.postMessage({ type: 'update', payload: newText }); } catch (err) { errorMessageDiv.textContent = 'Invalid JSON: ' + err.message; // Still send update so extension is aware of invalid state vscode.postMessage({ type: 'update', payload: newText }); } } /** * Handle messages received from the extension * @param {MessageEvent} event - The message event */ function handleExtensionMessages(event) { const message = event.data; switch (message.type) { case 'update': // Update editor content handleEditorUpdate(message); break; case 'updatePreview': // Update preview content handlePreviewUpdate(message); break; } } /** * Handle update messages for the editor content * @param {object} message - The update message */ function handleEditorUpdate(message) { const newText = message.text; if (newText !== lastKnownText) { console.log('Webview received editor update from extension.'); editor.value = newText; lastKnownText = newText; errorMessageDiv.textContent = ''; } } /** * Handle update messages for the preview content * @param {object} message - The update message */ function handlePreviewUpdate(message) { console.log("[Webview] Received 'updatePreview' from extension."); if (message.html !== undefined) { previewContentDiv.innerHTML = message.html; // Set rendered HTML console.log('[Webview] Preview HTML updated (length: ' + message.html.length + ')'); // Attempt to render Mermaid diagrams after updating HTML renderMermaidDiagrams(); } else { console.error("[Webview] Received 'updatePreview' message without html content."); } } /** * Render Mermaid diagrams in the preview content */ function renderMermaidDiagrams() { try { if (typeof mermaid !== 'undefined') { const mermaidElements = previewContentDiv.querySelectorAll('.mermaid'); if (mermaidElements && mermaidElements.length > 0) { console.log( '[Webview] Found ' + mermaidElements.length + ' mermaid elements. Rendering individually...' ); // Iterate through NodeList and render each element Array.from(mermaidElements).forEach((element, index) => { try { // Remove any previously rendered SVG to prevent duplicates const existingSvg = element.querySelector('svg'); if (existingSvg) { element.innerHTML = element.textContent || ''; // Restore original text } mermaid.run({ nodes: [element] }); // Render one element console.log('[Webview] Mermaid rendering attempted on element ' + index); } catch (renderErr) { console.error( '[Webview] Mermaid rendering failed for element ' + index + ':', renderErr ); // Add null check before setting innerHTML in catch block if (element) { element.innerHTML = '<pre>Mermaid Error:' + renderErr + '</pre>'; } } }); } } else { console.warn('[Webview] Mermaid library not found when trying to render.'); } } catch (err) { console.error('[Webview] Error rendering Mermaid:', err); } } /** * Attempt initial rendering of Mermaid diagrams */ function attemptInitialMermaidRender() { try { if (typeof mermaid !== 'undefined') { const initialMermaidElements = previewContentDiv.querySelectorAll('.mermaid'); if (initialMermaidElements && initialMermaidElements.length > 0) { console.log( '[Webview] Found ' + initialMermaidElements.length + ' mermaid elements for initial render. Rendering individually...' ); // Iterate through NodeList and render each element Array.from(initialMermaidElements).forEach((element, index) => { try { // Check if already rendered (simple check) if (!element.querySelector('svg')) { mermaid.run({ nodes: [element] }); // Render one element console.log('[Webview] Initial Mermaid rendering attempted on element ' + index); } else { console.log( '[Webview] Skipping initial render for already rendered element ' + index ); } } catch (renderErr) { console.error( '[Webview] Initial Mermaid rendering failed for element ' + index + ':', renderErr ); // Add null check before setting innerHTML in catch block if (element) { element.innerHTML = '<pre>Mermaid Error:' + renderErr + '</pre>'; } } }); } else { console.log('[Webview] No mermaid elements found for initial render.'); } } else { console.warn('[Webview] Mermaid library not found for initial render.'); } } catch (err) { console.error('[Webview] Error during initial Mermaid rendering:', err); } } /** * Sets up event listeners for the mode toggle buttons. */ function setupModeToggle() { const controls = document.getElementById('controls'); if (controls) { controls.addEventListener('click', (event) => { // Check if the clicked target is an HTMLButtonElement if (event.target instanceof HTMLButtonElement) { const button = event.target; // Cast to button element const mode = button.getAttribute('data-mode'); if (mode) { updateMode(mode); } } }); } else { console.error('[Webview] Controls element not found'); } } /** * Updates the body class and button states based on the selected mode. * @param {string} newMode - The mode to switch to ('editor-only', 'split', 'preview-only'). */ function updateMode(newMode) { // Remove existing mode classes from body document.body.classList.remove('show-editor-only', 'show-split', 'show-preview-only'); // Add the new mode class document.body.classList.add(`show-${newMode}`); // Update button active states const buttons = document.querySelectorAll('#controls button'); buttons.forEach(button => { if (button.getAttribute('data-mode') === newMode) { button.classList.add('active'); } else { button.classList.remove('active'); } }); console.log(`[Webview] Switched to mode: ${newMode}`); // Persist mode preference if needed (using vscode.setState) // vscode.setState({ viewMode: newMode }); } // Initialize after the DOM is fully loaded if (document.readyState === 'loading') { // Loading hasn't finished yet window.addEventListener('DOMContentLoaded', initialize); } else { // DOMContentLoaded has already fired initialize(); } })();

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/t3ta/memory-bank-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server