Skip to content

Commit 3f3ff4f

Browse files
jsollycursoragent
andauthored
Show human-readable labels on topic pills (#60)
Keep kebab-case tags as lookup keys, but render curated glossary display names (Title Case / brand forms) on shelf topic pills. Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent bb5138b commit 3f3ff4f

2 files changed

Lines changed: 26 additions & 5 deletions

File tree

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import { resolveChapterTag } from "$lib/far/glossary";
2+
import { resolveChapterTag, topicPillLabel } from "$lib/far/glossary";
33
import TermDefinitionPopover from "./TermDefinitionPopover.svelte";
44
55
let {
@@ -9,19 +9,20 @@
99
} = $props();
1010
1111
let term = $derived(resolveChapterTag(tag));
12+
let label = $derived(topicPillLabel(tag));
1213
</script>
1314

1415
{#if term}
1516
<TermDefinitionPopover
1617
{term}
1718
triggerClass="rounded-md bg-muted px-1.5 py-0.5 text-[0.65rem] text-muted-foreground outline-none transition-colors hover:bg-muted/80 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring sm:text-xs"
1819
>
19-
{tag}
20+
{label}
2021
</TermDefinitionPopover>
2122
{:else}
2223
<span
2324
class="rounded-md bg-muted px-1.5 py-0.5 text-[0.65rem] text-muted-foreground sm:text-xs"
2425
>
25-
{tag}
26+
{label}
2627
</span>
2728
{/if}

src/lib/far/glossary.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ export const CORE_GLOSSARY_TERMS: GlossaryTerm[] = [
104104
},
105105
{
106106
id: "sources-sought",
107-
term: "Sources sought",
108-
aliases: ["sources-sought", "Sources Sought", "sources sought notice"],
107+
term: "Sources Sought",
108+
aliases: ["sources-sought", "Sources sought", "sources sought notice"],
109109
definition:
110110
"A market-research notice that gathers capability evidence and often informs set-aside and acquisition strategy. It is not a solicitation for binding offers.",
111111
chapterId: "market-signal-to-solicitation",
@@ -515,6 +515,26 @@ export function resolveChapterTag(tag: string): GlossaryTerm | undefined {
515515
return byTagKey.get(normalizeKey(tag));
516516
}
517517

518+
/** Fallback when a tag has no glossary entry: `market-research` → `Market Research`. */
519+
function formatKebabAsTitle(tag: string): string {
520+
const parts = tag
521+
.trim()
522+
.split(/[-_]+/)
523+
.filter(Boolean);
524+
if (parts.length <= 1) {
525+
return tag.trim();
526+
}
527+
return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
528+
}
529+
530+
/**
531+
* Display label for a shelf topic pill.
532+
* Prefers the curated glossary `term`; otherwise formats the kebab-case key.
533+
*/
534+
export function topicPillLabel(tag: string): string {
535+
return resolveChapterTag(tag)?.term ?? formatKebabAsTitle(tag);
536+
}
537+
518538
/** All match strings for a term (canonical + aliases), longest first. */
519539
export function matchStringsForTerm(term: GlossaryTerm): string[] {
520540
return [term.term, ...(term.aliases ?? [])].sort((a, b) => b.length - a.length);

0 commit comments

Comments
 (0)