diff --git a/lib/Listener/BeforeTemplateRenderedListener.php b/lib/Listener/BeforeTemplateRenderedListener.php index 5ec35ec1..1b099e9b 100644 --- a/lib/Listener/BeforeTemplateRenderedListener.php +++ b/lib/Listener/BeforeTemplateRenderedListener.php @@ -14,6 +14,7 @@ use OCA\Whiteboard\Service\ConfigService; use OCP\AppFramework\Services\IInitialState; use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventDispatcher; use OCP\EventDispatcher\IEventListener; use OCP\Files\File; use OCP\Files\NotFoundException; @@ -28,6 +29,7 @@ class BeforeTemplateRenderedListener implements IEventListener { public function __construct( private IInitialState $initialState, private ConfigService $configService, + private IEventDispatcher $eventDispatcher, ) { } @@ -51,6 +53,11 @@ public function handle(Event $event): void { return; } + // Load the Text editor if available for table insertion support + if (class_exists('OCA\Text\Event\LoadEditor')) { + $this->eventDispatcher->dispatchTyped(new \OCA\Text\Event\LoadEditor()); + } + Util::addScript('whiteboard', 'whiteboard-main'); Util::addStyle('whiteboard', 'whiteboard-main'); diff --git a/src/components/TableEditorDialog.vue b/src/components/TableEditorDialog.vue index dd304876..79b26b13 100644 --- a/src/components/TableEditorDialog.vue +++ b/src/components/TableEditorDialog.vue @@ -61,10 +61,15 @@ export default defineComponent({ } // Convert HTML to markdown for the Text editor input - const contentForEditor = this.currentHtml && this.currentHtml.trim() + let contentForEditor = this.currentHtml && this.currentHtml.trim() ? this.generateMarkdownFromHtml(this.currentHtml) : '' + // If no content provided, create a minimal table with header and one body row + // This ensures the table editor recognizes it as a proper table with columns + if (!contentForEditor) { + contentForEditor = '| |\n| --- |\n| |\n' + } // Use the dedicated createTable function for table-only editing this.editor = await window.OCA.Text.createTable({ el: editorContainer, @@ -97,47 +102,25 @@ export default defineComponent({ } try { - // Extract HTML from the Text app's Tiptap editor to preserve all content (including pipe characters) - // The Text app's createTable() returns a wrapper object with a 'vm' property - // that contains the Vue instance rendering the editor component - let html = '' - - // Access the Vue instance created by the Text app - const vm = this.editor.vm - - // Navigate the component tree to find the Tiptap editor instance: - // vm.$children[0] is the Text app's table editor component - // which has an 'editor' property that is the actual Tiptap editor instance - if (vm && vm.$children && vm.$children.length > 0) { - const editorComponent = vm.$children[0] - - if (editorComponent && editorComponent.editor) { - // Get raw HTML from Tiptap editor (this is the reliable source of content) - const fullHtml = editorComponent.editor.getHTML() - const parser = new DOMParser() - const doc = parser.parseFromString(fullHtml, 'text/html') - const table = doc.querySelector('table') - - if (table) { - html = table.outerHTML - } else { - console.warn('No table found in HTML, using full HTML') - html = fullHtml - } - } + // Use Text app's getHTML() to extract clean HTML from Tiptap editor + const fullHtml = this.editor.getHTML() + if (!fullHtml) { + this.error = t('whiteboard', 'Failed to get editor content') + return } - if (!html) { - console.error('Could not extract HTML from Tiptap editor') - } + // Parse the HTML and extract just the table element + const parser = new DOMParser() + const doc = parser.parseFromString(fullHtml, 'text/html') + const table = doc.querySelector('table') - if (!html || !html.trim()) { - this.error = t('whiteboard', 'Failed to extract table content') + if (!table) { + this.error = t('whiteboard', 'No table found in editor content') return } this.$emit('submit', { - html: html.trim(), + html: table.outerHTML.trim(), }) this.show = false @@ -228,7 +211,9 @@ export default defineComponent({ {{ t('whiteboard', 'Loading editor…') }} -
+