@@ -36,6 +36,22 @@ const cleanups: Array<() => void> = []
3636afterEach ( ( ) => cleanups . splice ( 0 ) . forEach ( ( cleanup ) => cleanup ( ) ) )
3737
3838describe ( 'block images within Markdown paragraphs' , ( ) => {
39+ it ( 'retains a whitespace-only code span beside an image' , ( ) => {
40+ const paragraph : JSONContent = {
41+ type : 'paragraph' ,
42+ content : [
43+ { type : 'image' , attrs : { src : '/image.png' } } ,
44+ { type : 'text' , text : ' ' , marks : [ { type : 'code' } ] } ,
45+ ] ,
46+ }
47+ expect ( splitBlockImageParagraph ( paragraph ) ) . toEqual ( [
48+ {
49+ ...paragraph ,
50+ content : [ { type : 'inlineImage' , attrs : { src : '/image.png' } } , paragraph . content ! [ 1 ] ] ,
51+ } ,
52+ ] )
53+ } )
54+
3955 it ( 'does not mutate parsed nodes or trim meaningful code-span whitespace' , ( ) => {
4056 const paragraph : JSONContent = {
4157 type : 'paragraph' ,
@@ -50,22 +66,37 @@ describe('block images within Markdown paragraphs', () => {
5066 const original = structuredClone ( paragraph )
5167 const blocks = splitBlockImageParagraph ( paragraph )
5268 expect ( paragraph ) . toEqual ( original )
53- expect ( blocks [ 0 ] . content ) . toEqual ( [ { type : 'text' , text : 'Before' , marks : [ { type : 'bold' } ] } ] )
54- expect ( blocks [ 1 ] ) . toBe ( paragraph . content ?. [ 1 ] )
55- expect ( blocks [ 2 ] . content ) . toEqual ( [ { type : 'text' , text : ' code ' , marks : [ { type : 'code' } ] } ] )
69+ expect ( blocks ) . toHaveLength ( 1 )
70+ expect ( blocks [ 0 ] . content ) . toEqual (
71+ paragraph . content ?. map ( ( child ) =>
72+ child . type === 'image' ? { ...child , type : 'inlineImage' } : child
73+ )
74+ )
5675 } )
5776
5877 it ( 'preserves source order, text marks, and linked image dimensions and titles' , ( ) => {
5978 const markdown =
6079 '**Before** [<img src="https://example.test/sized.png" alt="Sized preview" width="320" height="180" title="Image title">](https://example.test/target "Link title") *after*  ` done `'
61- const doc = schema . nodeFromJSON ( parseMarkdownToDoc ( markdown ) )
80+ const root = schema . nodeFromJSON ( parseMarkdownToDoc ( markdown ) )
81+ expect ( root . childCount ) . toBe ( 1 )
82+ const doc = root . child ( 0 )
6283 expect ( ( ) => doc . check ( ) ) . not . toThrow ( )
6384 expect (
6485 Array . from ( { length : doc . childCount } , ( _ , index ) => doc . child ( index ) . type . name )
65- ) . toEqual ( [ 'paragraph' , 'image' , 'paragraph' , 'image' , 'paragraph' ] )
86+ ) . toEqual ( [
87+ 'text' ,
88+ 'text' ,
89+ 'inlineImage' ,
90+ 'text' ,
91+ 'text' ,
92+ 'text' ,
93+ 'inlineImage' ,
94+ 'text' ,
95+ 'text' ,
96+ ] )
6697 expect ( doc . child ( 0 ) . textContent ) . toBe ( 'Before' )
67- expect ( doc . child ( 0 ) . firstChild ?. marks . map ( ( mark ) => mark . type . name ) ) . toEqual ( [ 'bold' ] )
68- expect ( doc . child ( 1 ) . attrs ) . toMatchObject ( {
98+ expect ( doc . child ( 0 ) . marks . map ( ( mark ) => mark . type . name ) ) . toEqual ( [ 'bold' ] )
99+ expect ( doc . child ( 2 ) . attrs ) . toMatchObject ( {
69100 src : 'https://example.test/sized.png' ,
70101 alt : 'Sized preview' ,
71102 width : '320' ,
@@ -74,23 +105,25 @@ describe('block images within Markdown paragraphs', () => {
74105 href : 'https://example.test/target' ,
75106 hrefTitle : 'Link title' ,
76107 } )
77- expect ( doc . child ( 2 ) . textContent ) . toBe ( 'after' )
78- expect ( doc . child ( 2 ) . firstChild ? .marks . map ( ( mark ) => mark . type . name ) ) . toEqual ( [ 'italic' ] )
79- expect ( doc . child ( 3 ) . attrs . src ) . toBe ( 'https://example.test/second.png' )
80- expect ( doc . child ( 4 ) . textContent ) . toBe ( 'done' )
81- expect ( doc . child ( 4 ) . firstChild ? .marks . map ( ( mark ) => mark . type . name ) ) . toEqual ( [ 'code' ] )
108+ expect ( doc . child ( 4 ) . textContent ) . toBe ( 'after' )
109+ expect ( doc . child ( 4 ) . marks . map ( ( mark ) => mark . type . name ) ) . toEqual ( [ 'italic' ] )
110+ expect ( doc . child ( 6 ) . attrs . src ) . toBe ( 'https://example.test/second.png' )
111+ expect ( doc . child ( 8 ) . textContent ) . toBe ( 'done' )
112+ expect ( doc . child ( 8 ) . marks . map ( ( mark ) => mark . type . name ) ) . toEqual ( [ 'code' ] )
82113 const serialized = serializeMarkdownBody ( markdown )
83- expect ( schema . nodeFromJSON ( parseMarkdownToDoc ( serialized ) ) . toJSON ( ) ) . toEqual ( doc . toJSON ( ) )
114+ expect ( schema . nodeFromJSON ( parseMarkdownToDoc ( serialized ) ) . toJSON ( ) ) . toEqual ( root . toJSON ( ) )
84115 expect ( serializeMarkdownBody ( serialized ) ) . toBe ( serialized )
85116 } )
86117
87- it . each ( CASES ) ( 'keeps %s schema-valid and stable through save and reopen' , ( _label , markdown ) => {
118+ it . each ( CASES ) ( 'keeps %s schema-valid and stable through save and reopen' , ( label , markdown ) => {
88119 const parsed = schema . nodeFromJSON ( parseMarkdownToDoc ( markdown ) )
89120 expect ( ( ) => parsed . check ( ) ) . not . toThrow ( )
90121 const serialized = serializeMarkdownBody ( markdown )
91122 const reparsed = schema . nodeFromJSON ( parseMarkdownToDoc ( serialized ) )
92123 expect ( ( ) => reparsed . check ( ) ) . not . toThrow ( )
93- expect ( reparsed . toJSON ( ) ) . toEqual ( parsed . toJSON ( ) )
124+ if ( label !== 'marks spanning an image' ) expect ( reparsed . toJSON ( ) ) . toEqual ( parsed . toJSON ( ) )
125+ else expect ( serialized ) . toBe ( `**Before** ${ IMAGE } **after**` )
126+ expect ( reparsed . textContent ) . toBe ( parsed . textContent )
94127 expect ( serializeMarkdownBody ( serialized ) ) . toBe ( serialized )
95128 expect ( isRoundTripSafe ( markdown ) ) . toBe ( true )
96129 } )
0 commit comments