type PossibleCardlengths = 1 | 2 | 3 | 4 | 5 | 6 ; export enum FrontCardAppearance { splashPage = 'splash' , superHeroPage = 'super' , twoStoryPage = 'two' , twoStoryPageWithSidekick = 'two-plus-sidekick' , twoStoryStarter = 'two-starter' , threeStoryPage = 'three' , threeStoryPageWithSidekick = 'three-plus-sidekick' , threeStoryStarter = 'three-starter' , fourStoryPage = 'four' , fiveStoryPage = 'five' , sixStoryPage = 'six' } export type FrontCardAppearanceShort = PossibleCardlengths | FrontCardAppearance ; export type FrontCardList = FrontCardAppearanceShort [ ] ; export interface FrontCardsForArticleCount { [ countOfArticles ] : FrontCardList ; } export interface FrontCardAppearanceInfo { fits : PossibleCardlengths ; } const frontCardAppearanceInfo = { [ FrontCardAppearance . splashPage ] : { fits : 1 } , [ FrontCardAppearance . superHeroPage ] : { fits : 1 } , [ FrontCardAppearance . twoStoryPage ] : { fits : 2 } , [ FrontCardAppearance . twoStoryPageWithSidekick ] : { fits : 2 } , [ FrontCardAppearance . twoStoryStarter ] : { fits : 2 } , [ FrontCardAppearance . threeStoryPage ] : { fits : 3 } , [ FrontCardAppearance . threeStoryPageWithSidekick ] : { fits : 3 } , [ FrontCardAppearance . threeStoryStarter ] : { fits : 3 } , [ FrontCardAppearance . fourStoryPage ] : { fits : 4 } , [ FrontCardAppearance . fiveStoryPage ] : { fits : 5 } , [ FrontCardAppearance . sixStoryPage ] : { fits : 6 } , } ; export const defaultCardAppearances = { 1 : FrontCardAppearance . superHeroPage , 2 : FrontCardAppearance . twoStoryPage , 3 : FrontCardAppearance . threeStoryPage , 4 : FrontCardAppearance . fourStoryPage , 5 : FrontCardAppearance . fiveStoryPage , 6 : FrontCardAppearance . sixStoryPage , } ; export const getCardAppearanceInfoAndOverrides = ( card ) : FrontCardAppearanceInfo & { appearance : FrontCardAppearance ; } => { if ( typeof card === 'number' ) { return { appearance : defaultCardAppearances [ card ] , ... frontCardAppearanceInfo [ defaultCardAppearances [ card ] ] , } ; } return { appearance : card , ... frontCardAppearanceInfo [ card ] , } ; } ; const defaultLayout = ( cover = 1 ) : FrontCardsForArticleCount => { return { 0 : [ ] , 1 : [ cover ] , 2 : [ cover , 1 ] , 3 : [ cover , 2 ] , 4 : [ cover , 3 ] , 5 : [ cover , 4 ] , 6 : [ cover , 5 ] , 7 : [ cover , 2 , 4 ] , 8 : [ cover , 3 , 4 ] , 9 : [ cover , 3 , 5 ] , 10 : [ cover , 4 , 5 ] , 11 : [ cover , 2 , 3 , 5 ] , 12 : [ cover , 2 , 4 , 5 ] , 13 : [ cover , 3 , 4 , 5 ] , 14 : [ cover , 3 , 4 , 6 ] , 15 : [ cover , 2 , 3 , 4 , 5 ] , 16 : [ cover , 2 , 3 , 4 , 6 ] , 17 : [ cover , 2 , 3 , 5 , 6 ] , 18 : [ cover , 2 , 4 , 5 , 6 ] , 19 : [ cover , 2 , 4 , 5 , 6 ] , 20 : [ cover , 2 , 4 , 1 , 5 , 6 ] , 21 : [ cover , 2 , 3 , 4 , 5 , 6 ] , 22 : [ cover , 3 , 4 , 3 , 5 , 6 ] , 23 : [ cover , 3 , 4 , 5 , 4 , 6 ] , 24 : [ cover , 3 , 5 , 4 , 5 , 6 ] , 25 : [ cover , 5 , 4 , 5 , 4 , 6 ] , } ; } ; const thirdPageCoverLayout = ( cover = 1 ) : FrontCardsForArticleCount => { return { 0 : [ ] , 1 : [ cover ] , 2 : [ cover , 1 ] , 3 : [ cover , 2 ] , 4 : [ cover , 3 ] , 5 : [ cover , 4 ] , 6 : [ cover , 5 ] , 7 : [ cover , 2 , cover , 3 ] , 8 : [ cover , 3 , cover , 3 ] , 9 : [ cover , 3 , cover , 4 ] , 10 : [ cover , 4 , cover , 4 ] , 11 : [ cover , 2 , cover , 2 , 5 ] , 12 : [ cover , 2 , cover , 3 , 5 ] , 13 : [ cover , 3 , cover , 3 , 5 ] , 14 : [ cover , 3 , cover , 3 , 6 ] , 15 : [ cover , 2 , cover , 2 , 4 , 5 ] , 16 : [ cover , 2 , cover , 2 , 4 , 6 ] , 17 : [ cover , 2 , cover , 2 , 5 , 6 ] , 18 : [ cover , 2 , cover , 3 , 5 , 6 ] , 19 : [ cover , 3 , cover , 3 , 5 , 6 ] , 20 : [ cover , 3 , cover , 3 , 1 , 5 , 6 ] , 21 : [ cover , 2 , cover , 2 , 4 , 5 , 6 ] , 22 : [ cover , 3 , cover , 3 , 3 , 5 , 6 ] , 23 : [ cover , 3 , cover , 3 , 5 , 4 , 6 ] , 24 : [ cover , 3 , cover , 4 , 4 , 5 , 6 ] , 25 : [ cover , 5 , cover , 3 , 5 , 4 , 6 ] , } ; } ; /**
 * Denser layout than the default, that allows 2 or 3 articles on front card
 * (aka. front page) of a collection. The way the list is constructed is by
 * progressively increasing density, but avoiding repeating densities. (Ex. we
 * want to avoid 2 successive card with 4 articles each, to prevent a monotonous
 * layout.) Finally, we add a new card if we can't fit an additional article
 * anymore without getting a crowded and monotonous layout.
 *
 * We also make sure to progresively increase the number of the first card, but
 * never decrease it. This is because it'd otherwise be confusing for the
 * production/editioral team, where you might get better result adding 1 more
 * article in the collection, instead of breaking down a collection in smaller
 * ones.
 */ const denseLayout = ( ) : FrontCardsForArticleCount => { if ( process . env . EDITIONS_DENSE_LAYOUT !== 'enabled' ) return defaultLayout ( FrontCardAppearance . splashPage ) ; return { 0 : [ ] , 1 : [ FrontCardAppearance . splashPage ] , 2 : [ FrontCardAppearance . splashPage , FrontCardAppearance . splashPage ] , 3 : [ FrontCardAppearance . splashPage , 2 ] , 4 : [ 2 , 2 ] , 5 : [ 3 , 2 ] , 6 : [ 2 , 4 ] , 7 : [ 2 , 5 ] , 8 : [ 3 , 5 ] , 9 : [ 3 , 2 , 4 ] , 10 : [ 3 , 2 , 5 ] , 11 : [ 3 , 3 , 5 ] , 12 : [ 3 , 4 , 5 ] , 13 : [ 3 , 4 , 6 ] , 14 : [ 3 , 5 , 6 ] , 15 : [ 3 , 4 , 3 , 5 ] , 16 : [ 3 , 4 , 4 , 5 ] , 17 : [ 3 , 4 , 5 , 5 ] , 18 : [ 3 , 4 , 5 , 6 ] , 19 : [ 3 , 5 , 5 , 6 ] , 20 : [ 3 , 4 , 3 , 4 , 6 ] , 21 : [ 3 , 4 , 3 , 5 , 6 ] , 22 : [ 3 , 4 , 4 , 4 , 6 ] , 23 : [ 3 , 5 , 4 , 5 , 6 ] , 24 : [ 3 , 4 , 3 , 5 , 3 , 6 ] , 25 : [ 3 , 4 , 3 , 4 , 5 , 6 ] , } ; } ; export const getCardsForFront = ( frontName ) : FrontCardsForArticleCount => { switch ( frontName ) { case 'National' : case 'World' : case 'Financial' : return denseLayout ( ) ; case 'Crosswords' : return { 0 : [ ] , 1 : [ 2 ] , } ; case 'Life' : case 'Culture' : return thirdPageCoverLayout ( FrontCardAppearance . splashPage ) ; case 'Journal' : case 'Sport' : default : return defaultLayout ( FrontCardAppearance . splashPage ) ; } } ;