13 lines
1.1 KiB
TypeScript
13 lines
1.1 KiB
TypeScript
import type { KbxMenuSearchResult, KbxNavigationResolvedEntry } from '@kbx/contracts'
|
|
function normalize(value:string){return value.toLocaleLowerCase().replace(/\s+/g,'')}
|
|
export function searchNavigationEntries(entries:KbxNavigationResolvedEntry[], query:string, limit=12, priorityScreenIds:string[]=[]):KbxMenuSearchResult[]{
|
|
const q=normalize(query);const priority=new Map(priorityScreenIds.map((id,index)=>[id,index]))
|
|
return entries.map(entry=>{
|
|
const values=[entry.title,entry.screenId,entry.module,entry.section,...(entry.keywords??[])].map(normalize)
|
|
let score=q?0:(priority.has(entry.screenId)?1000-(priority.get(entry.screenId)??0):1)
|
|
for(const value of values){if(!q)continue;if(value===q)score=Math.max(score,100);else if(value.startsWith(q))score=Math.max(score,70);else if(value.includes(q))score=Math.max(score,40)}
|
|
if(q&&priority.has(entry.screenId)&&score>0)score+=5
|
|
return {screenId:entry.screenId,title:entry.title,module:entry.module,section:entry.section,path:entry.path,keywords:entry.keywords??[],score}
|
|
}).filter(x=>x.score>0).sort((a,b)=>b.score-a.score||a.title.localeCompare(b.title)).slice(0,limit)
|
|
}
|