@@ -14,6 +14,8 @@ import {
1414import auth from './auth.js' ;
1515import Request from './request.js' ;
1616
17+ const SEVERITY_ORDER = [ 'critical' , 'high' , 'medium' , 'low' ] ;
18+
1719export default class SecurityBlog extends SecurityRelease {
1820 req ;
1921
@@ -256,7 +258,8 @@ export default class SecurityBlog extends SecurityRelease {
256258 }
257259
258260 async getReportsTemplate ( content ) {
259- const reports = content . reports ;
261+ const reports = [ ...content . reports ] . sort ( ( a , b ) =>
262+ this . getSeverityOrder ( a ) - this . getSeverityOrder ( b ) ) ;
260263 let template = '' ;
261264 for ( const report of reports ) {
262265 const cveId = report . cveIds ?. join ( ', ' ) ;
@@ -282,22 +285,64 @@ export default class SecurityBlog extends SecurityRelease {
282285 return template ;
283286 }
284287
288+ getSeverityOrder ( report ) {
289+ const rating = report . severity ?. rating ?. toLowerCase ( ) ;
290+ const index = SEVERITY_ORDER . indexOf ( rating ) ;
291+ if ( index === - 1 ) return SEVERITY_ORDER . length ;
292+ return index ;
293+ }
294+
285295 getDependencyUpdatesTemplate ( dependencyUpdates ) {
286296 if ( typeof dependencyUpdates !== 'object' ) return '' ;
287297 if ( Object . keys ( dependencyUpdates ) . length === 0 ) return '' ;
288298 let template = '\nThis security release includes the following dependency' +
289299 ' updates to address public vulnerabilities:\n' ;
290- for ( const [ dependency , entry ] of Object . entries ( dependencyUpdates ) ) {
291- const releaseLines = getAffectedVersionLines ( entry . affectedVersions ) ;
292- const versions = Array . isArray ( entry . versions )
293- ? entry . versions . map ( ( v ) => ( typeof v === 'string' ? v : v . version ) )
294- : [ ] ;
295- const versionSuffix = versions . length ? ` (${ versions . join ( ', ' ) } )` : '' ;
296- template += `- ${ dependency } ${ versionSuffix } on ${ releaseLines . join ( ', ' ) } \n` ;
300+ if ( Array . isArray ( dependencyUpdates ) ) {
301+ for ( const dependency of dependencyUpdates ) {
302+ const title = this . formatDependencyUpdateTitle ( dependency ) ;
303+ const releaseLines = getAffectedVersionLines ( dependency . affectedVersions ) ;
304+ template += `- ${ title } on ${ releaseLines . join ( ', ' ) } \n` ;
305+ }
306+ return template ;
307+ }
308+
309+ for ( const [ dependency , { versions, affectedVersions } ] of Object . entries ( dependencyUpdates ) ) {
310+ const releaseLines = getAffectedVersionLines ( affectedVersions ) ;
311+ const formattedVersions = this . formatDependencyVersions ( versions ) ;
312+ const versionText = formattedVersions ? ` (${ formattedVersions } )` : '' ;
313+ template += `- ${ dependency } ${ versionText } on ${ releaseLines . join ( ', ' ) } \n` ;
297314 }
298315 return template ;
299316 }
300317
318+ formatDependencyUpdateVersion ( version ) {
319+ if ( typeof version === 'string' || typeof version === 'number' ) {
320+ return String ( version ) ;
321+ }
322+
323+ if ( ! version || typeof version !== 'object' ) return '' ;
324+
325+ return version . version || version . to || version . patched || version . name ||
326+ this . formatDependencyUpdateTitle ( version ) || version . url || JSON . stringify ( version ) ;
327+ }
328+
329+ formatDependencyVersions ( versions ) {
330+ if ( ! Array . isArray ( versions ) ) return '' ;
331+ return versions
332+ . map ( ( version ) => this . formatDependencyUpdateVersion ( version ) )
333+ . filter ( Boolean )
334+ . join ( ', ' ) ;
335+ }
336+
337+ formatDependencyUpdateTitle ( dependency ) {
338+ if ( ! dependency || typeof dependency !== 'object' ) return '' ;
339+ if ( ! dependency . title ) return dependency . name ?? '' ;
340+
341+ const titleSeparator = dependency . title . indexOf ( ':' ) ;
342+ if ( titleSeparator === - 1 ) return dependency . title ;
343+ return dependency . title . substring ( titleSeparator + ':' . length ) . trim ( ) ;
344+ }
345+
301346 async getDownloadsTemplate ( affectedVersions ) {
302347 let template = '' ;
303348 const versionsToBeReleased = ( await nv ( 'supported' ) ) . filter (
0 commit comments