import { matchSorter , rankings as matchSorterRankings } from 'match-sorter' ; import type { MdxListItem } from '~/types' ; import type { ReadRankings } from './blog.server' ; function getRankingLeader ( rankings ? ) { if ( ! rankings ) return null ; return rankings . reduce ( ( leader , rank ) => { if ( rank . ranking <= 0 ) return leader ; if ( ! leader || rank . ranking > leader . ranking ) return rank ; return leader ; } , null ) ; } function filterPosts ( posts , searchString ) { if ( ! searchString ) return posts ; const options = { keys : [ { key : 'frontmatter.title' , threshold : matchSorterRankings . CONTAINS , } , { key : 'frontmatter.categories' , threshold : matchSorterRankings . CONTAINS , maxRanking : matchSorterRankings . CONTAINS , } , { key : 'frontmatter.meta.keywords' , threshold : matchSorterRankings . CONTAINS , maxRanking : matchSorterRankings . CONTAINS , } , { key : 'frontmatter.description' , threshold : matchSorterRankings . CONTAINS , maxRanking : matchSorterRankings . CONTAINS , } , ] , } ; const allResults = matchSorter ( posts , searchString , options ) ; const searches = new Set ( searchString . split ( ' ' ) ) ; if ( searches . size < 2 ) { return allResults ; } const [ firstWord , ... restWords ] = searches . values ( ) ; if ( ! firstWord ) { return [ ] ; } const individualWordOptions = { ... options , keys : options . keys . map ( key => { return { ... key , maxRanking : matchSorterRankings . CASE_SENSITIVE_EQUAL , threshold : matchSorterRankings . WORD_STARTS_WITH , } ; } ) , } ; let individualWordResults = matchSorter ( posts , firstWord , individualWordOptions ) ; for ( const word of restWords ) { const searchResult = matchSorter ( individualWordResults , word , individualWordOptions ) ; individualWordResults = individualWordResults . filter ( r => searchResult . includes ( r ) ) ; } return Array . from ( new Set ( [ ... allResults , ... individualWordResults ] ) ) ; } export { filterPosts , getRankingLeader } ;