@@ -728,30 +728,13 @@ export class FloatContext {
728728 }
729729}
730730
731- export interface BlockContainerOfInlines extends BlockContainer {
732- children : IfcInline [ ] ;
733- }
734-
735- export type BlockLevel = BlockContainer | ReplacedBox ;
736-
737- export interface BlockContainerOfBlocks extends BlockContainer {
738- children : BlockLevel [ ] ;
739- }
740-
741- export class BlockContainer extends FormattingBox {
742- public children : IfcInline [ ] | BlockLevel [ ] ;
743-
731+ export abstract class BlockContainer extends FormattingBox {
744732 static ATTRS = {
745733 ...FormattingBox . ATTRS ,
746734 isInline : Box . BITS . isInline ,
747735 isBfcRoot : Box . BITS . isBfcRoot
748736 } ;
749737
750- constructor ( style : Style , children : IfcInline [ ] | BlockLevel [ ] , attrs : number ) {
751- super ( style , attrs ) ;
752- this . children = children ;
753- }
754-
755738 getLogSymbol ( ) {
756739 if ( this . isFloat ( ) ) {
757740 return '○︎' ;
@@ -802,27 +785,21 @@ export class BlockContainer extends FormattingBox {
802785 return Boolean ( this . bitfield & Box . BITS . enableLogging ) ;
803786 }
804787
805- isBlockContainerOfInlines ( ) : this is BlockContainerOfInlines {
806- return Boolean ( this . children . length && this . children [ 0 ] . isIfcInline ( ) ) ;
807- }
808-
809788 canCollapseThrough ( ) : boolean {
810789 const blockSize = this . style . getBlockSize ( this . getContainingBlock ( ) ) ;
811790
812791 if ( blockSize !== 'auto' && blockSize !== 0 ) return false ;
813792
814793 if ( this . isBlockContainerOfInlines ( ) ) {
815- const [ ifc ] = this . children ;
816- return ! ifc . hasText ( ) ;
817- } else {
794+ return ! this . ifc . hasText ( ) ;
795+ } else if ( this . isBlockContainerOfBlocks ( ) ) {
818796 return this . children . length === 0 ;
797+ } else {
798+ // TODO: this is a terrible situation, but where else does the method go?
799+ throw new Error ( 'Unreachable' ) ;
819800 }
820801 }
821802
822- isBlockContainerOfBlocks ( ) : this is BlockContainerOfBlocks {
823- return ! this . isBlockContainerOfInlines ( ) ;
824- }
825-
826803 propagate ( parent : Box ) {
827804 super . propagate ( parent ) ;
828805
@@ -832,14 +809,6 @@ export class BlockContainer extends FormattingBox {
832809 }
833810 }
834811
835- doTextLayout ( ctx : LayoutContext ) {
836- if ( ! this . isBlockContainerOfInlines ( ) ) throw new Error ( 'Children are block containers' ) ;
837- const [ ifc ] = this . children ;
838- const blockSize = this . style . getBlockSize ( this . getContainingBlock ( ) ) ;
839- ifc . doTextLayout ( ctx ) ;
840- if ( blockSize === 'auto' ) this . setBlockSize ( ifc . paragraph . getHeight ( ) ) ;
841- }
842-
843812 hasBackground ( ) {
844813 return this . style . hasPaint ( ) ;
845814 }
@@ -849,6 +818,40 @@ export class BlockContainer extends FormattingBox {
849818 }
850819}
851820
821+ export class BlockContainerOfInlines extends BlockContainer {
822+ ifc : IfcInline ;
823+
824+ constructor ( style : Style , ifc : IfcInline , attrs : number ) {
825+ super ( style , attrs ) ;
826+ this . ifc = ifc ;
827+ }
828+
829+ isBlockContainerOfInlines ( ) : this is BlockContainerOfInlines {
830+ return true ;
831+ }
832+
833+ doTextLayout ( ctx : LayoutContext ) {
834+ const blockSize = this . style . getBlockSize ( this . getContainingBlock ( ) ) ;
835+ this . ifc . doTextLayout ( ctx ) ;
836+ if ( blockSize === 'auto' ) this . setBlockSize ( this . ifc . paragraph . getHeight ( ) ) ;
837+ }
838+ }
839+
840+ export type BlockLevel = BlockContainer | ReplacedBox ;
841+
842+ export class BlockContainerOfBlocks extends BlockContainer {
843+ children : BlockLevel [ ] ;
844+
845+ constructor ( style : Style , children : BlockLevel [ ] , attrs : number ) {
846+ super ( style , attrs ) ;
847+ this . children = children ;
848+ }
849+
850+ isBlockContainerOfBlocks ( ) : this is BlockContainerOfBlocks {
851+ return true ;
852+ }
853+ }
854+
852855// §10.3.3
853856function doInlineBoxModelForBlockBox ( box : FormattingBox ) {
854857 const containingBlock = box . getContainingBlock ( ) ;
@@ -921,7 +924,7 @@ function doBlockBoxModelForBlockBox(box: BlockContainer) {
921924 const blockSize = box . style . getBlockSize ( containingBlock ) ;
922925
923926 if ( blockSize === 'auto' ) {
924- if ( box . children . length === 0 ) {
927+ if ( box . canCollapseThrough ( ) ) {
925928 box . setBlockSize ( 0 ) ; // Case 4
926929 } else {
927930 // Cases 1-4 should be handled by doBoxPositioning, where margin
@@ -1036,9 +1039,8 @@ export function layoutContribution(
10361039 isize = Math . max ( isize , layoutContribution ( child , mode ) ) ;
10371040 }
10381041 } else if ( box . isBlockContainerOfInlines ( ) ) {
1039- const [ ifc ] = box . children ;
1040- if ( ifc . shouldLayoutContent ( ) ) {
1041- isize = ifc . paragraph . contribution ( mode ) ;
1042+ if ( box . ifc . shouldLayoutContent ( ) ) {
1043+ isize = box . ifc . paragraph . contribution ( mode ) ;
10421044 }
10431045 }
10441046 }
@@ -1610,7 +1612,7 @@ function wrapInBlockContainer(parentEl: HTMLElement, inlines: InlineLevel[], tex
16101612 let attrs = Box . ATTRS . isAnonymous ;
16111613 if ( 'x-dropflow-log' in parentEl . attrs ) attrs |= Box . ATTRS . enableLogging ;
16121614 const ifc = new IfcInline ( anonStyle , text . value , inlines , attrs ) ;
1613- return new BlockContainer ( anonStyle , [ ifc ] , attrs ) ;
1615+ return new BlockContainerOfInlines ( anonStyle , ifc , attrs ) ;
16141616}
16151617
16161618function generateFormattingBox ( el : HTMLElement ) : BlockLevel {
@@ -1705,22 +1707,22 @@ export function generateBlockContainer(el: HTMLElement): BlockContainer {
17051707 attrs |= BlockContainer . ATTRS . isInline ;
17061708 }
17071709
1708- let children : BlockLevel [ ] | IfcInline [ ] ;
1710+ let box ;
17091711
17101712 if ( inlines . length ) {
17111713 if ( blocks . length ) {
17121714 blocks . push ( wrapInBlockContainer ( el , inlines , text ) ) ;
1713- children = blocks ;
1715+ box = new BlockContainerOfBlocks ( el . style , blocks , attrs ) ;
17141716 } else {
17151717 const anonComputedStyle = createStyle ( el . style , EMPTY_STYLE ) ;
17161718 const ifcAttrs = Box . ATTRS . isAnonymous | ( enableLogging ? Box . ATTRS . enableLogging : 0 ) ;
1717- children = [ new IfcInline ( anonComputedStyle , text . value , inlines , ifcAttrs ) ] ;
1719+ const ifc = new IfcInline ( anonComputedStyle , text . value , inlines , ifcAttrs ) ;
1720+ box = new BlockContainerOfInlines ( el . style , ifc , attrs ) ;
17181721 }
17191722 } else {
1720- children = blocks ;
1723+ box = new BlockContainerOfBlocks ( el . style , blocks , attrs ) ;
17211724 }
17221725
1723- const box = new BlockContainer ( el . style , children , attrs ) ;
17241726 el . boxes . push ( box ) ;
17251727 return box ;
17261728}
0 commit comments