/** Humanize a tag by replacing separators and capitalizing words. */ export function formatTag(tag: string): string { return tag.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()); } /** Tuple entries of group key and items. */ export type Grouped = ReadonlyArray; /** Group items by tag, assigning a default when none provided. */ export function groupByTag }>( items: ReadonlyArray, defaultTag = "General", ): Grouped { const groups: Record = {}; items.forEach((item) => { const tags = item.tags && item.tags.length ? item.tags : [defaultTag]; tags.forEach((tag) => { if (!groups[tag]) groups[tag] = []; groups[tag].push(item); }); }); return Object.entries(groups).sort(([a], [b]) => a.localeCompare(b)); } /** Group items by the first letter of their `term` property. */ export function groupByFirstLetter( items: ReadonlyArray, ): Grouped { const groups: Record = {}; items.forEach((item) => { const first = item.term.charAt(0).toUpperCase(); if (!groups[first]) groups[first] = []; groups[first].push(item); }); return Object.entries(groups).sort(([a], [b]) => a.localeCompare(b)); }