export function fallbackCompare<T>(itemA: T, itemB: T, query: IPreparedQuery, accessor: IItemAccessor<T>): number { // check for label + description length and prefer shorter const labelA = accessor.getItemLabel(itemA); const labelB = accessor.getItemLabel(itemB); const descriptionA = accessor.getItemDescription(itemA); const descriptionB = accessor.getItemDescription(itemB); const labelDescriptionALength = labelA.length + (descriptionA ? descriptionA.length : 0); const labelDescriptionBLength = labelB.length + (descriptionB ? descriptionB.length : 0); if (labelDescriptionALength !== labelDescriptionBLength) { return labelDescriptionALength - labelDescriptionBLength; } // check for path length and prefer shorter const pathA = accessor.getItemPath(itemA); const pathB = accessor.getItemPath(itemB); if (pathA && pathB && pathA.length !== pathB.length) { return pathA.length - pathB.length; } // 7.) finally we have equal scores and equal length, we fallback to comparer // compare by label if (labelA !== labelB) { return compareAnything(labelA, labelB, query.value); } // compare by description if (descriptionA && descriptionB && descriptionA !== descriptionB) { return compareAnything(descriptionA, descriptionB, query.value); } // compare by path if (pathA && pathB && pathA !== pathB) { return compareAnything(pathA, pathB, query.value); } // equal return 0; }
export function compareItemsByScore<T>(itemA: T, itemB: T, query: string, accessor: IItemAccessor<T>, cache: ScorerCache): number { const scoreA = scoreItem(itemA, query, accessor, cache).score; const scoreB = scoreItem(itemB, query, accessor, cache).score; // 1.) check for identity matches if (scoreA === PATH_IDENTITY_SCORE || scoreB === PATH_IDENTITY_SCORE) { if (scoreA !== scoreB) { return scoreA === PATH_IDENTITY_SCORE ? -1 : 1; } } // 2.) check for label prefix matches if (scoreA === LABEL_PREFIX_SCORE || scoreB === LABEL_PREFIX_SCORE) { if (scoreA !== scoreB) { return scoreA === LABEL_PREFIX_SCORE ? -1 : 1; } const labelA = accessor.getItemLabel(itemA); const labelB = accessor.getItemLabel(itemB); // prefer shorter names when both match on label prefix if (labelA.length !== labelB.length) { return labelA.length - labelB.length; } } // 3.) check for camelcase matches if (scoreA === LABEL_CAMELCASE_SCORE || scoreB === LABEL_CAMELCASE_SCORE) { if (scoreA !== scoreB) { return scoreA === LABEL_CAMELCASE_SCORE ? -1 : 1; } const labelA = accessor.getItemLabel(itemA); const labelB = accessor.getItemLabel(itemB); // prefer shorter names when both match on label camelcase if (labelA.length !== labelB.length) { return labelA.length - labelB.length; } } // 4.) check for label scores if (scoreA > LABEL_SCORE_THRESHOLD || scoreB > LABEL_SCORE_THRESHOLD) { if (scoreB < LABEL_SCORE_THRESHOLD) { return -1; } if (scoreA < LABEL_SCORE_THRESHOLD) { return 1; } } // 5.) check for path scores if (scoreA !== scoreB) { return scoreA > scoreB ? -1 : 1; } // 6.) at this point, scores are identical for both items so we start to sort by length // check for label + description length and prefer shorter const labelA = accessor.getItemLabel(itemA); const labelB = accessor.getItemLabel(itemB); const descriptionA = accessor.getItemDescription(itemA); const descriptionB = accessor.getItemDescription(itemB); const labelDescriptionALength = labelA.length + (descriptionA ? descriptionA.length : 0); const labelDescriptionBLength = labelB.length + (descriptionB ? descriptionB.length : 0); if (labelDescriptionALength !== labelDescriptionBLength) { return labelDescriptionALength - labelDescriptionBLength; } // check for path length and prefer shorter const pathA = accessor.getItemPath(itemA); const pathB = accessor.getItemPath(itemB); if (pathA && pathB && pathA.length !== pathB.length) { return pathA.length - pathB.length; } // 7.) finally we have equal scores and equal length, we fallback to comparer // compare by label if (labelA !== labelB) { return compareAnything(labelA, labelB, query); } // compare by description if (descriptionA && descriptionB && descriptionA !== descriptionB) { return compareAnything(descriptionA, descriptionB, query); } // compare by path if (pathA && pathB && pathA !== pathB) { return compareAnything(pathA, pathB, query); } // equal return 0; }