11import type { FC } from 'react' ;
2+ import semver from 'semver' ;
23
34import { getClientContext } from '#site/client-context' ;
45import CrossLink from '#site/components/Common/CrossLink' ;
56import getBlogData from '#site/next-data/blogData' ;
67import type { BlogCategory } from '#site/types' ;
78
9+ const extractVersionFromTitle = ( title : string ) : string | null => {
10+ const match = title . match ( / v ( \d + \. \d + \. \d + ) / ) ;
11+ return match ? match [ 1 ] : null ;
12+ } ;
13+
814const WithBlogCrossLinks : FC = ( ) => {
915 const { pathname } = getClientContext ( ) ;
1016
@@ -18,13 +24,30 @@ const WithBlogCrossLinks: FC = () => {
1824
1925 const { posts } = getBlogData ( category ) ;
2026
21- const currentItem = posts . findIndex (
27+ // Sort posts by semver for release category
28+ const sortedPosts =
29+ category === 'release'
30+ ? [ ...posts ] . sort ( ( a , b ) => {
31+ const versionA = extractVersionFromTitle ( a . title ) ;
32+ const versionB = extractVersionFromTitle ( b . title ) ;
33+
34+ if ( versionA && versionB ) {
35+ // Sort by semver in descending order (newest first)
36+ return semver . rcompare ( versionA , versionB ) ;
37+ }
38+
39+ // Fallback to date sorting if version extraction fails
40+ return b . date . getTime ( ) - a . date . getTime ( ) ;
41+ } )
42+ : posts ;
43+
44+ const currentItem = sortedPosts . findIndex (
2245 ( { slug } ) => slug === `/blog/${ category } /${ postname } `
2346 ) ;
2447
2548 const [ previousCrossLink , nextCrossLink ] = [
26- posts [ currentItem - 1 ] ,
27- posts [ currentItem + 1 ] ,
49+ sortedPosts [ currentItem - 1 ] ,
50+ sortedPosts [ currentItem + 1 ] ,
2851 ] ;
2952
3053 return (
0 commit comments