From 36bfb788a25e97b521b494d6bcddf60787505787 Mon Sep 17 00:00:00 2001 From: Jonas Date: Fri, 6 Sep 2024 14:28:43 +0200 Subject: [PATCH] fix(TaskList): Add class name to rendered HTML The upstream Tiptap tasklist implementation uses data-type attributes to identify task lists and task items. We use class names instead as we depend on the markdown-it-task-lists plugin. This fixes copy & paste of task lists. Fixes: #5237 Signed-off-by: Jonas --- cypress/e2e/shortcuts.spec.js | 2 +- cypress/e2e/workspace.spec.js | 2 +- src/nodes/TaskItem.js | 4 ++-- src/nodes/TaskList.js | 5 +++++ src/tests/tiptap.spec.js | 5 +++++ 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cypress/e2e/shortcuts.spec.js b/cypress/e2e/shortcuts.spec.js index f8783391765..2517432561a 100644 --- a/cypress/e2e/shortcuts.spec.js +++ b/cypress/e2e/shortcuts.spec.js @@ -45,7 +45,7 @@ describe('keyboard shortcuts', () => { it('codeblock', () => testShortcut(`${modKey}{alt}c`, 'pre')) it('ordered-list', () => testShortcut(`${modKey}{shift}7`, 'ol')) it('unordered-list', () => testShortcut(`${modKey}{shift}8`, 'ul')) - it('task-list', () => testShortcut(`${modKey}{shift}9`, 'ul[data-type="taskList"]')) + it('task-list', () => testShortcut(`${modKey}{shift}9`, 'ul.contains-task-list')) // Headings const levels = [1, 2, 3, 4, 5, 6] diff --git a/cypress/e2e/workspace.spec.js b/cypress/e2e/workspace.spec.js index db1b914d6bb..ca57890d033 100644 --- a/cypress/e2e/workspace.spec.js +++ b/cypress/e2e/workspace.spec.js @@ -111,7 +111,7 @@ describe('Workspace', function() { ;[ ['unordered-list', 'ul'], ['ordered-list', 'ol'], - ['task-list', 'ul[data-type="taskList"]'], + ['task-list', 'ul.contains-task-list'], ].forEach(([button, tag]) => testButton(button, tag, 'List me')) }) diff --git a/src/nodes/TaskItem.js b/src/nodes/TaskItem.js index 7e6305abf8a..de927c35842 100644 --- a/src/nodes/TaskItem.js +++ b/src/nodes/TaskItem.js @@ -42,7 +42,7 @@ const TaskItem = TipTapTaskItem.extend({ ], renderHTML({ node, HTMLAttributes }) { - const listAttributes = { class: 'checkbox-item' } + const listAttributes = { class: 'task-list-item checkbox-item' } const checkboxAttributes = { type: 'checkbox', class: '', contenteditable: false } if (node.attrs.checked) { checkboxAttributes.checked = true @@ -70,7 +70,7 @@ const TaskItem = TipTapTaskItem.extend({ state.renderContent(node) }, - addInputRules() { + addInputRules() { return [ ...this.parent(), wrappingInputRule({ diff --git a/src/nodes/TaskList.js b/src/nodes/TaskList.js index 38f1faac0fd..c02e960fddf 100644 --- a/src/nodes/TaskList.js +++ b/src/nodes/TaskList.js @@ -4,6 +4,7 @@ */ import TiptapTaskList from '@tiptap/extension-task-list' +import { mergeAttributes } from '@tiptap/core' const TaskList = TiptapTaskList.extend({ @@ -14,6 +15,10 @@ const TaskList = TiptapTaskList.extend({ }, ], + renderHTML({ HTMLAttributes }) { + return ['ul', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { class: 'contains-task-list' }), 0] + }, + addAttributes() { return { ...this.parent?.(), diff --git a/src/tests/tiptap.spec.js b/src/tests/tiptap.spec.js index dd3018ce349..4b6f4244496 100644 --- a/src/tests/tiptap.spec.js +++ b/src/tests/tiptap.spec.js @@ -25,4 +25,9 @@ describe('TipTap', () => { const markdown = 'Hard line break \nNext Paragraph' expect(renderedHTML(markdown)).toEqual('

Hard line break
Next Paragraph

') }) + + it('render taskList', () => { + const markdown = '* [ ] item 1\n' + expect(renderedHTML(markdown)).toEqual('') + }) })