diff --git a/packages/markdown/src/lib/MarkdownPlugin.ts b/packages/markdown/src/lib/MarkdownPlugin.ts index 1e9ff29e44..872251154b 100644 --- a/packages/markdown/src/lib/MarkdownPlugin.ts +++ b/packages/markdown/src/lib/MarkdownPlugin.ts @@ -63,7 +63,7 @@ export const MarkdownPlugin = createTSlatePlugin({ .extend(({ api }) => ({ parser: { deserialize: ({ data }) => api.markdown.deserialize(data), - format: 'text/plain', + format: 'text/markdown', query: ({ data, dataTransfer }) => { const htmlData = dataTransfer.getData('text/html'); diff --git a/packages/markdown/src/lib/deserializer/utils/deserializeMd.spec.tsx b/packages/markdown/src/lib/deserializer/utils/deserializeMd.spec.tsx index 9716518543..66f2ba8941 100644 --- a/packages/markdown/src/lib/deserializer/utils/deserializeMd.spec.tsx +++ b/packages/markdown/src/lib/deserializer/utils/deserializeMd.spec.tsx @@ -341,11 +341,29 @@ describe('deserializeMd', () => { expect(deserializeMd(editor, input)).toEqual(output); }); - it('should deserialize headings', () => { - const input = Array.from( - { length: 6 }, - (_, i) => `${'#'.repeat(i + 1)} Heading ${i + 1}` - ).join('\n\n'); + it('should deserialize line break tags', () => { + const input = 'Line 1
Line 2'; + + const output = ( + + + Line 1 + {'\n'} + Line 2 + + + ); + + expect(deserializeMd(editor, input)).toEqual(output); + }); + + it('should deserialize all heading levels (h1-h6)', () => { + const input = `# Heading 1 +## Heading 2 +### Heading 3 +#### Heading 4 +##### Heading 5 +###### Heading 6`; const output = ( @@ -361,16 +379,54 @@ describe('deserializeMd', () => { expect(deserializeMd(editor, input)).toEqual(output); }); - it('should deserialize line break tags', () => { - const input = 'Line 1
Line 2'; + it('should handle headings with multiple spaces', () => { + const input = `# Heading 1 +## Heading 2 +### Heading 3 `; const output = ( - - Line 1 - {'\n'} - Line 2 - + Heading 1 + Heading 2 + Heading 3 + + ); + + expect(deserializeMd(editor, input)).toEqual(output); + }); + + it('should handle more than 6 hashes as h6', () => { + const input = `####### Should be h6`; + + const output = ( + + Should be h6 + + ); + + expect(deserializeMd(editor, input)).toEqual(output); + }); + + it('should handle headings with no space after hash', () => { + const input = `#No space`; + + const output = ( + + #No space + + ); + + expect(deserializeMd(editor, input)).toEqual(output); + }); + + it('should handle escaped hashes', () => { + const input = `\\# Not a heading +\\## Also not a heading`; + + const output = ( + + # Not a heading + ## Also not a heading ); diff --git a/packages/markdown/src/lib/remark-slate/remarkDefaultElementRules.ts b/packages/markdown/src/lib/remark-slate/remarkDefaultElementRules.ts index 21eac86b12..f8a43d757a 100644 --- a/packages/markdown/src/lib/remark-slate/remarkDefaultElementRules.ts +++ b/packages/markdown/src/lib/remark-slate/remarkDefaultElementRules.ts @@ -39,6 +39,8 @@ export const remarkDefaultElementRules: RemarkElementRules = { }, heading: { transform: (node, options) => { + const depth = Math.max(1, Math.min(6, node.depth ?? 1)); + const headingType = { 1: 'h1', 2: 'h2', @@ -46,11 +48,13 @@ export const remarkDefaultElementRules: RemarkElementRules = { 4: 'h4', 5: 'h5', 6: 'h6', - }[node.depth ?? 1]; + }[depth]; + + const type = options.editor.getType({ key: headingType ?? 'h3' }); return { children: remarkTransformElementChildren(node, options), - type: options.editor.getType({ key: headingType }), + type: type, }; }, }, diff --git a/packages/markdown/src/lib/remark-slate/remarkTransformElementChildren.ts b/packages/markdown/src/lib/remark-slate/remarkTransformElementChildren.ts index fd4fa7c936..886d17185b 100644 --- a/packages/markdown/src/lib/remark-slate/remarkTransformElementChildren.ts +++ b/packages/markdown/src/lib/remark-slate/remarkTransformElementChildren.ts @@ -8,9 +8,9 @@ export const remarkTransformElementChildren = ( node: MdastNode, options: RemarkPluginOptions ): TDescendant[] => { - const { children } = node; + const { children = [] } = node; - if (!children || children.length === 0) { + if (children.length === 0) { return [{ text: '' }]; }