@@ -1658,84 +1658,121 @@ const collapse = children => {
16581658 return newChildren ;
16591659} ;
16601660
1661- const spaceLimited = ( itemsAndGroups , max ) => {
1661+ const spaceLimited = (
1662+ itemsAndGroups ,
1663+ max ,
1664+ filteredChildrenLineReserved = false
1665+ ) => {
1666+ if ( max < 1 ) {
1667+ return {
1668+ children : undefined ,
1669+ filteredChildren : getTotalItems ( itemsAndGroups )
1670+ } ;
1671+ }
16621672 /** @type {any[] | undefined } */
16631673 let children = undefined ;
16641674 /** @type {number | undefined } */
16651675 let filteredChildren = undefined ;
16661676 // This are the groups, which take 1+ lines each
1667- const groups = itemsAndGroups . filter ( c => c . children || c . filteredChildren ) ;
1677+ const groups = [ ] ;
16681678 // The sizes of the groups are stored in groupSizes
1669- const groupSizes = groups . map ( g => getItemSize ( g ) ) ;
1679+ const groupSizes = [ ] ;
16701680 // This are the items, which take 1 line each
1671- const items = itemsAndGroups . filter ( c => ! c . children && ! c . filteredChildren ) ;
1681+ const items = [ ] ;
16721682 // The total of group sizes
1673- let groupsSize = groupSizes . reduce ( ( a , b ) => a + b , 0 ) ;
1683+ let groupsSize = 0 ;
1684+
1685+ for ( const itemOrGroup of itemsAndGroups ) {
1686+ // is item
1687+ if ( ! itemOrGroup . children && ! itemOrGroup . filteredChildren ) {
1688+ items . push ( itemOrGroup ) ;
1689+ } else {
1690+ groups . push ( itemOrGroup ) ;
1691+ const size = getItemSize ( itemOrGroup ) ;
1692+ groupSizes . push ( size ) ;
1693+ groupsSize += size ;
1694+ }
1695+ }
1696+
16741697 if ( groupsSize + items . length <= max ) {
16751698 // The total size in the current state fits into the max
16761699 // keep all
1677- children = groups . concat ( items ) ;
1678- } else if (
1679- groups . length > 0 &&
1680- groups . length + Math . min ( 1 , items . length ) < max
1681- ) {
1682- // If each group would take 1 line the total would be below the maximum
1683- // collapse some groups, keep items
1684- while ( groupsSize + items . length + ( filteredChildren ? 1 : 0 ) > max ) {
1700+ children = groups . length > 0 ? groups . concat ( items ) : items ;
1701+ } else if ( groups . length === 0 ) {
1702+ // slice items to max
1703+ // inner space marks that lines for filteredChildren already reserved
1704+ const limit = max - ( filteredChildrenLineReserved ? 0 : 1 ) ;
1705+ filteredChildren = items . length - limit ;
1706+ items . length = limit ;
1707+ children = items ;
1708+ } else {
1709+ // limit is the size when all groups are collapsed
1710+ const limit =
1711+ groups . length +
1712+ ( filteredChildrenLineReserved || items . length === 0 ? 0 : 1 ) ;
1713+ if ( limit < max ) {
16851714 // calculate how much we are over the size limit
16861715 // this allows to approach the limit faster
1687- // it's always > 1
1688- const oversize =
1689- items . length + groupsSize + ( filteredChildren ? 1 : 0 ) - max ;
1690- // Find the maximum group and process only this one
1691- const maxGroupSize = Math . max ( ...groupSizes ) ;
1692- if ( maxGroupSize < items . length ) {
1693- filteredChildren = items . length ;
1694- items . length = 0 ;
1695- continue ;
1696- }
1697- for ( let i = 0 ; i < groups . length ; i ++ ) {
1698- if ( groupSizes [ i ] === maxGroupSize ) {
1699- const group = groups [ i ] ;
1700- // run this algorithm recursively and limit the size of the children to
1701- // current size - oversize / number of groups
1702- // So it should always end up being smaller
1703- const headerSize = ! group . children
1704- ? 0
1705- : group . filteredChildren
1706- ? 2
1707- : 1 ;
1708- const limited = spaceLimited (
1709- group . children ,
1710- groupSizes [ i ] - headerSize - oversize / groups . length
1711- ) ;
1712- groups [ i ] = {
1713- ...group ,
1714- children : limited . children ,
1715- filteredChildren :
1716- ( group . filteredChildren || 0 ) + limited . filteredChildren
1717- } ;
1718- const newSize = getItemSize ( groups [ i ] ) ;
1719- groupsSize -= groupSizes [ i ] - newSize ;
1720- groupSizes [ i ] = newSize ;
1721- break ;
1716+ let oversize ;
1717+ // If each group would take 1 line the total would be below the maximum
1718+ // collapse some groups, keep items
1719+ while (
1720+ ( oversize =
1721+ groupsSize +
1722+ items . length +
1723+ ( filteredChildren && ! filteredChildrenLineReserved ? 1 : 0 ) -
1724+ max ) > 0
1725+ ) {
1726+ // Find the maximum group and process only this one
1727+ const maxGroupSize = Math . max ( ...groupSizes ) ;
1728+ if ( maxGroupSize < items . length ) {
1729+ filteredChildren = items . length ;
1730+ items . length = 0 ;
1731+ continue ;
1732+ }
1733+ for ( let i = 0 ; i < groups . length ; i ++ ) {
1734+ if ( groupSizes [ i ] === maxGroupSize ) {
1735+ const group = groups [ i ] ;
1736+ // run this algorithm recursively and limit the size of the children to
1737+ // current size - oversize / number of groups
1738+ // So it should always end up being smaller
1739+ const headerSize = group . filteredChildren ? 2 : 1 ;
1740+ const limited = spaceLimited (
1741+ group . children ,
1742+ maxGroupSize -
1743+ // we should use ceil to always feet in max
1744+ Math . ceil ( oversize / groups . length ) -
1745+ // we substitute size of group head
1746+ headerSize ,
1747+ headerSize === 2
1748+ ) ;
1749+ groups [ i ] = {
1750+ ...group ,
1751+ children : limited . children ,
1752+ filteredChildren : limited . filteredChildren
1753+ ? ( group . filteredChildren || 0 ) + limited . filteredChildren
1754+ : group . filteredChildren
1755+ } ;
1756+ const newSize = getItemSize ( groups [ i ] ) ;
1757+ groupsSize -= maxGroupSize - newSize ;
1758+ groupSizes [ i ] = newSize ;
1759+ break ;
1760+ }
17221761 }
17231762 }
1763+ children = groups . concat ( items ) ;
1764+ } else if ( limit === max ) {
1765+ // If we have only enough space to show one line per group and one line for the filtered items
1766+ // collapse all groups and items
1767+ children = collapse ( groups ) ;
1768+ filteredChildren = items . length ;
1769+ } else {
1770+ // If we have no space
1771+ // collapse complete group
1772+ filteredChildren = getTotalItems ( itemsAndGroups ) ;
17241773 }
1725- children = groups . concat ( items ) ;
1726- } else if (
1727- groups . length > 0 &&
1728- groups . length + Math . min ( 1 , items . length ) <= max
1729- ) {
1730- // If we have only enough space to show one line per group and one line for the filtered items
1731- // collapse all groups and items
1732- children = groups . length ? collapse ( groups ) : undefined ;
1733- filteredChildren = items . length ;
1734- } else {
1735- // If we have no space
1736- // collapse complete group
1737- filteredChildren = getTotalItems ( itemsAndGroups ) ;
17381774 }
1775+
17391776 return {
17401777 children,
17411778 filteredChildren
@@ -1777,6 +1814,9 @@ const reasonGroup = (children, reasons) => {
17771814 } ;
17781815} ;
17791816
1817+ const GROUP_EXTENSION_REGEXP = / ( \. [ ^ . ] + ?) (?: \? | (?: \+ \d + m o d u l e s ? ) ? $ ) / ;
1818+ const GROUP_PATH_REGEXP = / ( .+ ) [ / \\ ] [ ^ / \\ ] + ?(?: \? | (?: \+ \d + m o d u l e s ? ) ? $ ) / ;
1819+
17801820/** @type {Record<string, (groupConfigs: GroupConfig[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void> } */
17811821const ASSETS_GROUPERS = {
17821822 _ : ( groupConfigs , context , options ) => {
@@ -1825,10 +1865,10 @@ const ASSETS_GROUPERS = {
18251865 groupConfigs . push ( {
18261866 getKeys : asset => {
18271867 const extensionMatch =
1828- groupAssetsByExtension && / ( \. [ ^ . ] + ) (?: \? . * | $ ) / . exec ( asset . name ) ;
1868+ groupAssetsByExtension && GROUP_EXTENSION_REGEXP . exec ( asset . name ) ;
18291869 const extension = extensionMatch ? extensionMatch [ 1 ] : "" ;
18301870 const pathMatch =
1831- groupAssetsByPath && / ( . + ) [ / \\ ] [ ^ / \\ ] + (?: \? . * | $ ) / . exec ( asset . name ) ;
1871+ groupAssetsByPath && GROUP_PATH_REGEXP . exec ( asset . name ) ;
18321872 const path = pathMatch ? pathMatch [ 1 ] . split ( / [ / \\ ] / ) : [ ] ;
18331873 const keys = [ ] ;
18341874 if ( groupAssetsByPath ) {
@@ -2025,10 +2065,10 @@ const MODULES_GROUPERS = type => ({
20252065 const dataUrl = / ^ d a t a : [ ^ , ; ] + / . exec ( resource ) ;
20262066 if ( dataUrl ) return [ dataUrl [ 0 ] ] ;
20272067 const extensionMatch =
2028- groupModulesByExtension && / ( \. [ ^ . ] + ) (?: \? . * | $ ) / . exec ( resource ) ;
2068+ groupModulesByExtension && GROUP_EXTENSION_REGEXP . exec ( resource ) ;
20292069 const extension = extensionMatch ? extensionMatch [ 1 ] : "" ;
20302070 const pathMatch =
2031- groupModulesByPath && / ( . + ) [ / \\ ] [ ^ / \\ ] + (?: \? . * | $ ) / . exec ( resource ) ;
2071+ groupModulesByPath && GROUP_PATH_REGEXP . exec ( resource ) ;
20322072 const path = pathMatch ? pathMatch [ 1 ] . split ( / [ / \\ ] / ) : [ ] ;
20332073 const keys = [ ] ;
20342074 if ( groupModulesByPath ) {
0 commit comments