@@ -280,6 +280,167 @@ describe('splitBlock', () => {
280280 expect ( attrs . paragraphProperties ?. styleId ) . toBeUndefined ( ) ;
281281 } ) ;
282282
283+ it ( 'does not inherit linked paragraph styles onto the newly created paragraph' , ( ) => {
284+ mockEditor . converter = {
285+ translatedLinkedStyles : {
286+ styles : {
287+ Heading2 : { styleId : 'Heading2' , type : 'paragraph' , link : 'Heading2Char' } ,
288+ } ,
289+ } ,
290+ } ;
291+ const paragraphType = { name : 'paragraph' , isTextblock : true , hasRequiredAttrs : vi . fn ( ( ) => false ) } ;
292+ const parentNode = {
293+ contentMatchAt : vi . fn ( ( ) => ( {
294+ edgeCount : 1 ,
295+ edge : vi . fn ( ( ) => ( { type : paragraphType } ) ) ,
296+ } ) ) ,
297+ } ;
298+
299+ const sourceAttrs = {
300+ paragraphProperties : { styleId : 'Heading2' , keep : true } ,
301+ } ;
302+ const $from = createMockResolvedPos ( {
303+ depth : 1 ,
304+ parent : {
305+ isBlock : true ,
306+ content : { size : 10 } ,
307+ type : { name : 'paragraph' } ,
308+ inlineContent : true ,
309+ attrs : sourceAttrs ,
310+ } ,
311+ parentOffset : 5 ,
312+ node : vi . fn ( ( depth ) => {
313+ if ( depth === - 1 ) return parentNode ;
314+ return { type : { name : 'paragraph' } , attrs : sourceAttrs } ;
315+ } ) ,
316+ } ) ;
317+ const $to = createMockResolvedPos ( {
318+ pos : 5 ,
319+ parent : { isBlock : true , content : { size : 10 } , type : { name : 'paragraph' } , inlineContent : true } ,
320+ parentOffset : 10 ,
321+ } ) ;
322+
323+ mockTr . selection = { $from, $to } ;
324+ mockState . selection = mockTr . selection ;
325+ mockTr . doc = {
326+ resolve : vi . fn ( ( ) => $from ) ,
327+ } ;
328+
329+ const command = splitBlock ( ) ;
330+ command ( { tr : mockTr , state : mockState , dispatch : ( ) => { } , editor : mockEditor } ) ;
331+
332+ const splitTypes = mockTr . split . mock . calls [ 0 ] [ 2 ] ;
333+ expect ( splitTypes ?. [ 0 ] ?. attrs ?. paragraphProperties ?. styleId ) . toBeNull ( ) ;
334+ expect ( splitTypes ?. [ 0 ] ?. attrs ?. paragraphProperties ?. keep ) . toBe ( true ) ;
335+ expect ( sourceAttrs . paragraphProperties . styleId ) . toBe ( 'Heading2' ) ;
336+ } ) ;
337+
338+ it ( 'preserves linked paragraph styles when the split creates a non-empty following paragraph' , ( ) => {
339+ mockEditor . converter = {
340+ translatedLinkedStyles : {
341+ styles : {
342+ Heading2 : { styleId : 'Heading2' , type : 'paragraph' , link : 'Heading2Char' } ,
343+ } ,
344+ } ,
345+ } ;
346+ const paragraphType = { name : 'paragraph' , isTextblock : true , hasRequiredAttrs : vi . fn ( ( ) => false ) } ;
347+ const parentNode = {
348+ contentMatchAt : vi . fn ( ( ) => ( {
349+ edgeCount : 1 ,
350+ edge : vi . fn ( ( ) => ( { type : paragraphType } ) ) ,
351+ } ) ) ,
352+ } ;
353+
354+ const sourceAttrs = {
355+ paragraphProperties : { styleId : 'Heading2' , keep : true } ,
356+ } ;
357+ const $from = createMockResolvedPos ( {
358+ depth : 1 ,
359+ parent : {
360+ isBlock : true ,
361+ content : { size : 10 } ,
362+ type : { name : 'paragraph' } ,
363+ inlineContent : true ,
364+ attrs : sourceAttrs ,
365+ } ,
366+ parentOffset : 5 ,
367+ node : vi . fn ( ( depth ) => {
368+ if ( depth === - 1 ) return parentNode ;
369+ return { type : { name : 'paragraph' } , attrs : sourceAttrs } ;
370+ } ) ,
371+ } ) ;
372+ const $to = createMockResolvedPos ( {
373+ pos : 5 ,
374+ parent : { isBlock : true , content : { size : 10 } , type : { name : 'paragraph' } , inlineContent : true } ,
375+ parentOffset : 5 ,
376+ } ) ;
377+
378+ mockTr . selection = { $from, $to } ;
379+ mockState . selection = mockTr . selection ;
380+ mockTr . doc = {
381+ resolve : vi . fn ( ( ) => $from ) ,
382+ } ;
383+
384+ const command = splitBlock ( ) ;
385+ command ( { tr : mockTr , state : mockState , dispatch : ( ) => { } , editor : mockEditor } ) ;
386+
387+ const splitTypes = mockTr . split . mock . calls [ 0 ] [ 2 ] ;
388+ expect ( splitTypes ) . toBeUndefined ( ) ;
389+ } ) ;
390+
391+ it ( 'preserves ordinary paragraph styles on the newly created paragraph' , ( ) => {
392+ mockEditor . converter = {
393+ translatedLinkedStyles : {
394+ styles : {
395+ BodyText : { styleId : 'BodyText' , type : 'paragraph' } ,
396+ } ,
397+ } ,
398+ } ;
399+ const paragraphType = { name : 'paragraph' , isTextblock : true , hasRequiredAttrs : vi . fn ( ( ) => false ) } ;
400+ const parentNode = {
401+ contentMatchAt : vi . fn ( ( ) => ( {
402+ edgeCount : 1 ,
403+ edge : vi . fn ( ( ) => ( { type : paragraphType } ) ) ,
404+ } ) ) ,
405+ } ;
406+
407+ const sourceAttrs = {
408+ paragraphProperties : { styleId : 'BodyText' , keep : true } ,
409+ } ;
410+ const $from = createMockResolvedPos ( {
411+ depth : 1 ,
412+ parent : {
413+ isBlock : true ,
414+ content : { size : 10 } ,
415+ type : { name : 'paragraph' } ,
416+ inlineContent : true ,
417+ attrs : sourceAttrs ,
418+ } ,
419+ parentOffset : 5 ,
420+ node : vi . fn ( ( depth ) => {
421+ if ( depth === - 1 ) return parentNode ;
422+ return { type : { name : 'paragraph' } , attrs : sourceAttrs } ;
423+ } ) ,
424+ } ) ;
425+ const $to = createMockResolvedPos ( {
426+ pos : 5 ,
427+ parent : { isBlock : true , content : { size : 10 } , type : { name : 'paragraph' } , inlineContent : true } ,
428+ parentOffset : 10 ,
429+ } ) ;
430+
431+ mockTr . selection = { $from, $to } ;
432+ mockState . selection = mockTr . selection ;
433+ mockTr . doc = {
434+ resolve : vi . fn ( ( ) => $from ) ,
435+ } ;
436+
437+ const command = splitBlock ( ) ;
438+ command ( { tr : mockTr , state : mockState , dispatch : ( ) => { } , editor : mockEditor } ) ;
439+
440+ const splitTypes = mockTr . split . mock . calls [ 0 ] [ 2 ] ;
441+ expect ( splitTypes ?. [ 0 ] ?. attrs ?. paragraphProperties ?. styleId ) . toBe ( 'BodyText' ) ;
442+ } ) ;
443+
283444 it ( 'does not mutate source attrs when removing nested override attributes' , ( ) => {
284445 const paragraphType = { name : 'paragraph' , isTextblock : true , hasRequiredAttrs : vi . fn ( ( ) => false ) } ;
285446 const parentNode = {
0 commit comments