diff --git a/src/nodes/Image.ts b/src/nodes/Image.ts index 405dc92a694..303564640a7 100644 --- a/src/nodes/Image.ts +++ b/src/nodes/Image.ts @@ -54,6 +54,10 @@ const Image = TiptapImage.extend({ return { ...this.parent?.() as ImageOptions, noLazyImages: false, + // Markdown files can legitimately contain base64 data: URI images. + // Parsing them is required, otherwise they are silently dropped on + // the next save (issue #9108). + allowBase64: true, } }, diff --git a/src/nodes/ImageInline.ts b/src/nodes/ImageInline.ts index 75dbeeea00f..168aaabab32 100644 --- a/src/nodes/ImageInline.ts +++ b/src/nodes/ImageInline.ts @@ -49,6 +49,9 @@ const ImageInline = TiptapImage.extend({ ...this.parent?.() as ImageOptions, noLazyImages: false, inline: true, + // See Image.ts: data: URI images must survive an edit round-trip + // instead of being dropped on save (issue #9108). + allowBase64: true, } }, diff --git a/src/tests/markdown.spec.js b/src/tests/markdown.spec.js index 2f5bb9e5011..57015b673c1 100644 --- a/src/tests/markdown.spec.js +++ b/src/tests/markdown.spec.js @@ -38,6 +38,13 @@ describe('Markdown though editor', () => { expect(markdownThroughEditor('~~Test~~')).toBe('~~Test~~') expect(markdownThroughEditor('Have an `inline code` element')).toBe('Have an `inline code` element') }) + test('images with data: URI survive a round-trip (#9108)', ({ markdownThroughEditor }) => { + const dataUri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==' + // standalone image (block level, wrapped in a figure) + expect(markdownThroughEditor(`![pixel](${dataUri})`)).toBe(`![pixel](${dataUri})`) + // inline image inside a paragraph + expect(markdownThroughEditor(`Before ![pixel](${dataUri}) after`)).toBe(`Before ![pixel](${dataUri}) after`) + }) test('ul', ({ markdownThroughEditor }) => { expect(markdownThroughEditor('+ foo\n+ bar')).toBe('+ foo\n+ bar') expect(markdownThroughEditor('* foo\n* bar')).toBe('* foo\n* bar')