// Integration for converting pasted spreadsheet tables to Markdown tables in EasyMDE/CodeMirror // Handles both HTML tables (from Google Sheets) and tab-separated values window.markdownTablePaste = { findEditor: function(editorId) { let textarea = null; let codeMirror = null; if (editorId) { const editorElement = document.getElementById(editorId); if (editorElement) { textarea = editorElement.querySelector('textarea'); const cmEl = editorElement.querySelector('.CodeMirror'); if (cmEl && cmEl.CodeMirror) { codeMirror = cmEl.CodeMirror; } } } else { const containers = document.querySelectorAll('.EasyMDEContainer'); if (containers.length > 0) { const lastContainer = containers[containers.length - 1]; textarea = lastContainer.querySelector('textarea'); const cmEl = lastContainer.querySelector('.CodeMirror'); if (cmEl && cmEl.CodeMirror) { codeMirror = cmEl.CodeMirror; } } } if (!codeMirror && textarea && window.EasyMDE) { const easyMDEInstances = window.EasyMDE.instances || []; for (let i = 0; i < easyMDEInstances.length; i++) { const instance = easyMDEInstances[i]; if (instance && instance.codemirror) { const cmTextarea = instance.codemirror.getTextArea(); if (cmTextarea === textarea) { codeMirror = instance.codemirror; break; } } } if (!codeMirror && textarea.parentElement) { const parent = textarea.parentElement; if (parent._easyMDEInstance && parent._easyMDEInstance.codemirror) { codeMirror = parent._easyMDEInstance.codemirror; } } } return { textarea, codeMirror }; }, getValue: function(editorId) { const found = this.findEditor(editorId); if (found.codeMirror) { return found.codeMirror.getValue(); } if (found.textarea) { return found.textarea.value; } return null; }, setValue: function(editorId, text) { const found = this.findEditor(editorId); if (found.codeMirror) { found.codeMirror.setValue(text ?? ''); return true; } if (found.textarea) { found.textarea.value = text ?? ''; found.textarea.dispatchEvent(new Event('input', { bubbles: true })); return true; } return false; }, insertAtCursor: function(editorId, text) { const found = this.findEditor(editorId); if (found.codeMirror) { found.codeMirror.replaceSelection(text); found.codeMirror.focus(); return true; } if (found.textarea) { const start = found.textarea.selectionStart || 0; const end = found.textarea.selectionEnd || 0; const before = found.textarea.value.substring(0, start); const after = found.textarea.value.substring(end); found.textarea.value = before + text + after; found.textarea.selectionStart = found.textarea.selectionEnd = before.length + text.length; found.textarea.dispatchEvent(new Event('input', { bubbles: true })); found.textarea.focus(); return true; } return false; }, /** * Initializes paste handler for a MarkdownEditor instance. * Finds the textarea or CodeMirror instance created by EasyMDE and attaches paste event handler. * @param {string} editorId - The ID of the editor wrapper element, or null to find by class */ initialize: function(editorId) { let attempts = 0; const maxAttempts = 5; const tryInitialize = function() { attempts++; const found = window.markdownTablePaste.findEditor(editorId); const textarea = found.textarea; const codeMirror = found.codeMirror; if (textarea || codeMirror) { const target = codeMirror || textarea; if (target) { // Add paste handler if (codeMirror) { codeMirror.on('paste', function(cm, event) { handleManualPaste(event, cm); }); } else if (textarea) { textarea.addEventListener('paste', function(event) { handleManualPaste(event, textarea); }, true); // Use capture phase to intercept early } return; // Success - we're done } } // If we didn't find the textarea, retry if (attempts < maxAttempts) { setTimeout(tryInitialize, attempts * 100); } }; // Start with initial delay to allow EasyMDE to initialize setTimeout(tryInitialize, 100); } }; /** * Handler for converting pasted spreadsheet tables to Markdown tables. * Handles both HTML tables (from Google Sheets) and tab-separated values. */ function handleManualPaste(event, target) { const clipboardData = event.clipboardData || window.clipboardData; if (!clipboardData) return; const html = clipboardData.getData('text/html'); const text = clipboardData.getData('text/plain'); let markdownTable = null; // Check if HTML contains a table if (html && html.includes('