@@ -652,6 +652,17 @@ const printDiffs = (base, head, options) => {
652652 }
653653
654654 const moves = detectMoves ( baseContents , headContents ) ;
655+
656+ const baseFeaturePaths = collectFeatures ( baseContents ) ;
657+ const headFeaturePaths = collectFeatures ( headContents ) ;
658+ const movedDests = new Set ( moves . values ( ) ) ;
659+ const addedFeatures = [ ...headFeaturePaths . keys ( ) ]
660+ . filter ( ( p ) => ! baseFeaturePaths . has ( p ) && ! movedDests . has ( p ) )
661+ . sort ( ) ;
662+ const removedFeatures = [ ...baseFeaturePaths . keys ( ) ]
663+ . filter ( ( p ) => ! headFeaturePaths . has ( p ) && ! moves . has ( p ) )
664+ . sort ( ) ;
665+
655666 projectMoves ( baseContents , moves ) ;
656667
657668 const baseData = flattenObject ( baseContents ) ;
@@ -852,6 +863,54 @@ const printDiffs = (base, head, options) => {
852863 }
853864 } ;
854865
866+ if ( addedFeatures . length ) {
867+ if ( options . format === 'html' ) {
868+ console . log ( '<h4>New features</h4>' ) ;
869+ console . log ( '<ul>' ) ;
870+ for ( const path of addedFeatures ) {
871+ const lastDot = path . lastIndexOf ( '.' ) ;
872+ const parent = lastDot === - 1 ? '' : path . slice ( 0 , lastDot + 1 ) ;
873+ const leaf = lastDot === - 1 ? path : path . slice ( lastDot + 1 ) ;
874+ console . log (
875+ `<li>${ parent } <ins style="color: green">${ leaf } </ins></li>` ,
876+ ) ;
877+ }
878+ console . log ( '</ul>' ) ;
879+ } else {
880+ console . log ( styleText ( 'bold' , 'New features:' ) ) ;
881+ for ( const path of addedFeatures ) {
882+ const lastDot = path . lastIndexOf ( '.' ) ;
883+ const parent = lastDot === - 1 ? '' : path . slice ( 0 , lastDot + 1 ) ;
884+ const leaf = lastDot === - 1 ? path : path . slice ( lastDot + 1 ) ;
885+ console . log ( ` ${ parent } ${ styleText ( 'green' , leaf ) } ` ) ;
886+ }
887+ console . log ( '' ) ;
888+ }
889+ }
890+
891+ if ( removedFeatures . length ) {
892+ if ( options . format === 'html' ) {
893+ console . log ( '<h4>Removed features</h4>' ) ;
894+ console . log ( '<ul>' ) ;
895+ for ( const path of removedFeatures ) {
896+ const lastDot = path . lastIndexOf ( '.' ) ;
897+ const parent = lastDot === - 1 ? '' : path . slice ( 0 , lastDot + 1 ) ;
898+ const leaf = lastDot === - 1 ? path : path . slice ( lastDot + 1 ) ;
899+ console . log ( `<li>${ parent } <del style="color: red">${ leaf } </del></li>` ) ;
900+ }
901+ console . log ( '</ul>' ) ;
902+ } else {
903+ console . log ( styleText ( 'bold' , 'Removed features:' ) ) ;
904+ for ( const path of removedFeatures ) {
905+ const lastDot = path . lastIndexOf ( '.' ) ;
906+ const parent = lastDot === - 1 ? '' : path . slice ( 0 , lastDot + 1 ) ;
907+ const leaf = lastDot === - 1 ? path : path . slice ( lastDot + 1 ) ;
908+ console . log ( ` ${ parent } ${ styleText ( 'red' , leaf ) } ` ) ;
909+ }
910+ console . log ( '' ) ;
911+ }
912+ }
913+
855914 if ( moves . size ) {
856915 if ( options . format === 'html' ) {
857916 console . log ( '<h4>Moved features</h4>' ) ;
@@ -869,6 +928,10 @@ const printDiffs = (base, head, options) => {
869928 }
870929 }
871930
931+ if ( addedFeatures . length || removedFeatures . length || moves . size ) {
932+ console . log ( '' ) ;
933+ }
934+
872935 for ( const entry of entries ) {
873936 /** @type {string | null } */
874937 let previousKey = null ;
0 commit comments