diff --git a/src/lib/components/common/RichTextInput.svelte b/src/lib/components/common/RichTextInput.svelte index e4c469acd5..53a042b6f5 100644 --- a/src/lib/components/common/RichTextInput.svelte +++ b/src/lib/components/common/RichTextInput.svelte @@ -94,6 +94,12 @@ } }); + // Registered after use(gfm) to override its checkbox rule; taskListItems owns the marker. + turndownService.addRule('taskItemCheckbox', { + filter: (node) => node.nodeName === 'INPUT' && node.getAttribute('type') === 'checkbox', + replacement: () => '' + }); + turndownService.addRule('taskListItems', { filter: (node) => node.nodeName === 'LI' && @@ -101,7 +107,8 @@ node.getAttribute('data-checked') === 'false'), replacement: function (content, node) { const checked = node.getAttribute('data-checked') === 'true'; - content = content.replace(/^\s+/, ''); + // Trim TipTap's block wrapper; 4-space continuation keeps sublists and fences nested. + content = content.trim().replace(/\n(?=.)/g, '\n '); return `- [${checked ? 'x' : ' '}] ${content}\n`; } });