docs: add companies frontmatter, schema, and rendering in badges & appendix pages

This commit is contained in:
Prad Nukala committed 2026-10-14 15:52:02 -04:00
1 parent c753937852
commit f6c580b14b
109 files changed
+1218 -12

No files matched your search

+115 -5
View File
@@ -7,8 +7,12 @@
* shows (the term's icon in the tag's colour from `lib/tag-colors.ts`, over
* the same tag universe `ProblemBadges.astro` colours) and lists the problem
* pages whose badge links here: the backlinks a per-term page used to have.
* The filter is a custom element over static markup, the way the Carousel
* is built; with no JS the page is the full glossary.
* After the terms, a Companies section: one card per company any problem
* page's `companies:` names (`companies.ts`), the target of that company's
* pill in the page's company table, listing the solved problems it asked in
* the last six months and how recently. The filter is a custom element over
* static markup, the way the Carousel is built; with no JS the page is the
* full glossary.
*/
import { getEntry } from "astro:content";
import data from "blume:data";
@@ -16,6 +20,7 @@ import Icon from "blume/components/Icon.astro";
import { withBase } from "blume/components/islands/base-path.ts";
import PageLayout from "blume/components/layout/PageLayout.astro";
import { APPENDIX } from "../appendix.ts";
import { RECENCY, RECENCY_LABEL, companyHref, type Company } from "../companies.ts";
import { tagColors } from "../lib/tag-colors.ts";
import { TOPIC_LANDINGS, tagTarget, type TopicTag } from "../topic-landings.ts";
@@ -35,6 +40,7 @@ const problems = await Promise.all(
name: name!,
difficulty: entry?.data.sidebar?.badge as string | undefined,
tags: (entry?.data.topics ?? []) as TopicTag[],
companies: (entry?.data.companies ?? []) as Company[],
};
}),
);
@@ -55,6 +61,21 @@ const terms = Object.entries(APPENDIX)
}))
.sort((a, b) => a.name.localeCompare(b.name));
// Every company a problem page names, A–Z; its solved problems most recent
// window first, then by number.
const companies = [
...Map.groupBy(
problems.flatMap((p) => p.companies.map((c) => ({ ...p, company: c.name, period: c.period }))),
(row) => row.company,
),
]
.map(([name, rows]) => ({
name,
id: companyHref(name).slice("/appendix#".length),
problems: rows.sort((a, b) => RECENCY.indexOf(a.period) - RECENCY.indexOf(b.period) || a.num - b.num),
}))
.sort((a, b) => a.name.localeCompare(b.name));
const sections = new Map<string, typeof terms>();
for (const term of terms) {
const letter = term.name[0]!.toUpperCase();
@@ -73,7 +94,7 @@ const DIFFICULTY: Record<string, { label: string; class: string }> = {
Hard: { label: "Hard", class: "border-chart-3/40 bg-chart-3/10 text-chart-3" },
};
const description =
"The LeetCode topics the campaign meets without teaching them as a topic: what each one means, and the solved problems that use it.";
"The LeetCode topics the campaign meets without teaching them as a topic, what each one means and the solved problems that use it, then the companies that asked those problems in the last six months.";
---
<PageLayout
@@ -115,6 +136,17 @@ const description =
),
)
}
{
companies.length > 0 && (
<a
href="#companies"
data-letter-link="companies"
class="inline-flex h-7 items-center justify-center rounded-md px-2 text-foreground no-underline transition-colors hover:bg-muted"
>
Companies
</a>
)
}
</nav>
<label class="relative block sm:w-64">
<span class="sr-only">Filter terms</span>
@@ -125,7 +157,7 @@ const description =
/>
<input
type="search"
placeholder={`Filter ${terms.length} terms`}
placeholder={`Filter ${terms.length} terms, ${companies.length} companies`}
class="w-full rounded-md border border-border bg-background py-1.5 pr-3 pl-8 text-foreground text-sm outline-none transition-colors placeholder:text-muted-foreground focus:border-foreground/40"
/>
</label>
@@ -231,7 +263,85 @@ const description =
</section>
))
}
<p data-empty hidden class="mt-10 text-muted-foreground">No term matches that filter.</p>
{
companies.length > 0 && (
<section id="companies" data-letter="companies" class="scroll-mt-24 pt-10">
<h2 class="m-0 text-2xl font-semibold text-foreground">Companies</h2>
<div class="mt-4 grid gap-4 sm:grid-cols-2">
{companies.map((company) => (
<article
id={company.id}
data-term={`${company.name} company`.toLowerCase()}
class="flex scroll-mt-24 flex-col rounded-lg border border-border bg-muted/30 p-5 transition-colors target:border-foreground/40 target:bg-muted/60"
>
<header class="flex items-start gap-3">
<span class="flex size-9 shrink-0 items-center justify-center rounded-md border border-border text-muted-foreground">
<Icon name="building-2" size={18} />
</span>
<div class="min-w-0 flex-1">
<h3 class="m-0 text-base font-semibold leading-snug">
<a class="text-foreground no-underline hover:underline" href={`#${company.id}`}>
{company.name}
</a>
</h3>
<p class="m-0 mt-0.5 font-mono text-[11px] uppercase tracking-wide text-muted-foreground">
Company · {company.problems.length} solved
</p>
</div>
</header>
<solved-pages class="mt-4 block border-border border-t pt-3">
<ul class="m-0 list-none p-0 text-sm">
{company.problems.map((p, i) => (
<li data-page={Math.floor(i / PAGE_SIZE)}>
<a
class="-mx-2 flex items-baseline gap-3 rounded-md px-2 py-1 text-foreground no-underline transition-colors hover:bg-muted"
href={withBase(p.route)}
>
<span class="w-10 shrink-0 text-right font-mono text-muted-foreground text-xs tabular-nums">
{p.num}
</span>
<span class="min-w-0 flex-1 truncate">{p.name}</span>
<span class="shrink-0 text-muted-foreground text-xs">within {RECENCY_LABEL[p.period]}</span>
{p.difficulty && DIFFICULTY[p.difficulty] && (
<span
class:list={[
"shrink-0 rounded-full border px-2 py-px font-mono text-[11px] leading-4",
DIFFICULTY[p.difficulty]!.class,
]}
>
{DIFFICULTY[p.difficulty]!.label}
</span>
)}
</a>
</li>
))}
</ul>
{company.problems.length > PAGE_SIZE && (
<nav
aria-label={`${company.name} solved pages`}
class="mt-2 flex flex-wrap justify-center gap-1 font-mono text-xs"
hidden
>
{Array.from({ length: Math.ceil(company.problems.length / PAGE_SIZE) }, (_, page) => (
<button
type="button"
data-goto={page}
aria-label={`Page ${page + 1}`}
class="inline-flex size-7 cursor-pointer items-center justify-center rounded-md border border-transparent text-muted-foreground tabular-nums transition-colors hover:bg-muted hover:text-foreground aria-[current=page]:border-border aria-[current=page]:bg-muted aria-[current=page]:text-foreground"
>
{page + 1}
</button>
))}
</nav>
)}
</solved-pages>
</article>
))}
</div>
</section>
)
}
<p data-empty hidden class="mt-10 text-muted-foreground">Nothing matches that filter.</p>
</appendix-filter>
</section>
</PageLayout>