@@ -892,7 +892,111 @@ describe('remeasureParagraph', () => {
892892 const block = createBlock ( [ textRun ( 'Hello' ) , { kind : 'lineBreak' } as Run , textRun ( 'World' ) ] ) ;
893893 const measure = remeasureParagraph ( block , 200 ) ;
894894
895- expect ( measure . lines . length ) . toBeGreaterThanOrEqual ( 1 ) ;
895+ expect ( measure . lines ) . toHaveLength ( 2 ) ;
896+ expect ( measure . lines [ 0 ] . fromRun ) . toBe ( 0 ) ;
897+ expect ( measure . lines [ 0 ] . toRun ) . toBe ( 0 ) ;
898+ expect ( measure . lines [ 1 ] . fromRun ) . toBe ( 2 ) ;
899+ expect ( measure . lines [ 1 ] . toRun ) . toBe ( 2 ) ;
900+ } ) ;
901+
902+ it ( 'creates an empty line for leading lineBreak at start of paragraph' , ( ) => {
903+ const block = createBlock ( [ { kind : 'lineBreak' } as Run , textRun ( 'Text' ) ] ) ;
904+ const measure = remeasureParagraph ( block , 200 ) ;
905+
906+ expect ( measure . lines ) . toHaveLength ( 2 ) ;
907+ expect ( measure . lines [ 0 ] . fromRun ) . toBe ( 0 ) ;
908+ expect ( measure . lines [ 0 ] . toRun ) . toBe ( 0 ) ;
909+ expect ( measure . lines [ 0 ] . toChar ) . toBe ( 0 ) ;
910+ expect ( measure . lines [ 1 ] . fromRun ) . toBe ( 1 ) ;
911+ expect ( measure . lines [ 1 ] . toRun ) . toBe ( 1 ) ;
912+ } ) ;
913+
914+ it ( 'preserves multiple explicit lineBreak boundaries' , ( ) => {
915+ const block = createBlock ( [
916+ textRun ( 'One' ) ,
917+ { kind : 'lineBreak' } as Run ,
918+ textRun ( 'Two' ) ,
919+ { kind : 'lineBreak' } as Run ,
920+ textRun ( 'Three' ) ,
921+ ] ) ;
922+ const measure = remeasureParagraph ( block , 200 ) ;
923+
924+ expect ( measure . lines ) . toHaveLength ( 3 ) ;
925+ expect ( measure . lines [ 0 ] . fromRun ) . toBe ( 0 ) ;
926+ expect ( measure . lines [ 0 ] . toRun ) . toBe ( 0 ) ;
927+ expect ( measure . lines [ 1 ] . fromRun ) . toBe ( 2 ) ;
928+ expect ( measure . lines [ 1 ] . toRun ) . toBe ( 2 ) ;
929+ expect ( measure . lines [ 2 ] . fromRun ) . toBe ( 4 ) ;
930+ expect ( measure . lines [ 2 ] . toRun ) . toBe ( 4 ) ;
931+ } ) ;
932+
933+ it ( 'preserves trailing explicit lineBreak as final empty line' , ( ) => {
934+ const block = createBlock ( [ textRun ( 'Hello' ) , { kind : 'lineBreak' } as Run ] ) ;
935+ const measure = remeasureParagraph ( block , 200 ) ;
936+
937+ expect ( measure . lines ) . toHaveLength ( 2 ) ;
938+ expect ( measure . lines [ 0 ] . fromRun ) . toBe ( 0 ) ;
939+ expect ( measure . lines [ 0 ] . toRun ) . toBe ( 0 ) ;
940+ // Final empty line should be anchored to trailing break run.
941+ expect ( measure . lines [ 1 ] . fromRun ) . toBe ( 1 ) ;
942+ expect ( measure . lines [ 1 ] . toRun ) . toBe ( 1 ) ;
943+ expect ( measure . lines [ 1 ] . toChar ) . toBe ( 0 ) ;
944+ } ) ;
945+
946+ it ( 'handles a single explicit lineBreak run as the only paragraph content' , ( ) => {
947+ const block = createBlock ( [ { kind : 'lineBreak' } as Run ] ) ;
948+ const measure = remeasureParagraph ( block , 200 ) ;
949+
950+ expect ( measure . lines ) . toHaveLength ( 1 ) ;
951+ expect ( measure . lines [ 0 ] . fromRun ) . toBe ( 0 ) ;
952+ expect ( measure . lines [ 0 ] . toRun ) . toBe ( 0 ) ;
953+ expect ( measure . lines [ 0 ] . fromChar ) . toBe ( 0 ) ;
954+ expect ( measure . lines [ 0 ] . toChar ) . toBe ( 0 ) ;
955+ } ) ;
956+
957+ it ( 'uses previous text font size for trailing explicit lineBreak empty line height' , ( ) => {
958+ const block = createBlock ( [ textRun ( 'Heading' , { fontSize : 24 } ) , { kind : 'lineBreak' } as Run ] ) ;
959+ const measure = remeasureParagraph ( block , 200 ) ;
960+
961+ expect ( measure . lines ) . toHaveLength ( 2 ) ;
962+ expect ( measure . lines [ 0 ] . lineHeight ) . toBe ( 24 * 1.2 ) ;
963+ expect ( measure . lines [ 1 ] . fromRun ) . toBe ( 1 ) ;
964+ expect ( measure . lines [ 1 ] . toRun ) . toBe ( 1 ) ;
965+ expect ( measure . lines [ 1 ] . lineHeight ) . toBe ( 24 * 1.2 ) ;
966+ } ) ;
967+
968+ it ( 'preserves multiple trailing explicit lineBreak runs as multiple empty lines' , ( ) => {
969+ const block = createBlock ( [ textRun ( 'Hello' ) , { kind : 'lineBreak' } as Run , { kind : 'lineBreak' } as Run ] ) ;
970+ const measure = remeasureParagraph ( block , 200 ) ;
971+
972+ expect ( measure . lines ) . toHaveLength ( 3 ) ;
973+ expect ( measure . lines [ 0 ] . fromRun ) . toBe ( 0 ) ;
974+ expect ( measure . lines [ 0 ] . toRun ) . toBe ( 0 ) ;
975+ expect ( measure . lines [ 1 ] . fromRun ) . toBe ( 1 ) ;
976+ expect ( measure . lines [ 1 ] . toRun ) . toBe ( 1 ) ;
977+ expect ( measure . lines [ 1 ] . toChar ) . toBe ( 0 ) ;
978+ expect ( measure . lines [ 2 ] . fromRun ) . toBe ( 2 ) ;
979+ expect ( measure . lines [ 2 ] . toRun ) . toBe ( 2 ) ;
980+ expect ( measure . lines [ 2 ] . toChar ) . toBe ( 0 ) ;
981+ } ) ;
982+
983+ it ( 'matches measureParagraphBlock for text + break + break + text' , ( ) => {
984+ const block = createBlock ( [
985+ textRun ( 'A' ) ,
986+ { kind : 'lineBreak' } as Run ,
987+ { kind : 'lineBreak' } as Run ,
988+ textRun ( 'B' ) ,
989+ ] ) ;
990+ const measure = remeasureParagraph ( block , 200 ) ;
991+
992+ expect ( measure . lines ) . toHaveLength ( 3 ) ;
993+ expect ( measure . lines [ 0 ] . fromRun ) . toBe ( 0 ) ;
994+ expect ( measure . lines [ 0 ] . toRun ) . toBe ( 0 ) ;
995+ expect ( measure . lines [ 1 ] . fromRun ) . toBe ( 2 ) ;
996+ expect ( measure . lines [ 1 ] . toRun ) . toBe ( 2 ) ;
997+ expect ( measure . lines [ 1 ] . toChar ) . toBe ( 0 ) ;
998+ expect ( measure . lines [ 2 ] . fromRun ) . toBe ( 3 ) ;
999+ expect ( measure . lines [ 2 ] . toRun ) . toBe ( 3 ) ;
8961000 } ) ;
8971001
8981002 it ( 'handles tabs followed immediately by line break' , ( ) => {
0 commit comments