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

+42 -1
View File
@@ -1,6 +1,7 @@
---
/**
* The MDX `wrapper`: the badge row between a page's description and its body.
* The MDX `wrapper`: the badge row (and, below it, the company table) between
* a page's description and its body.
* Blume's page template renders the title and description itself and then
* the MDX content, with no slot in between, so wrapping the content is the
* only way to land right after the description. MDX hands a wrapper no
@@ -26,12 +27,19 @@
* - `issue:` (problem pages, written by sync) is the problem's GitHub issue
* URL, a neutral "Issue #N" badge with the GitHub mark, right after
* "Explanation" at the end of the row.
* - `companies:` (problem pages, written by sync; `companies.ts`) is the
* companies that asked the problem in the last six months, a table laid
* out like Blume's TypeTable under the badge row: each company a pill
* linking to its card in the Appendix's Companies section, the most recent
* window it asked in, and its frequency there (relative within that
* company and window, so a bar of 100 is its most-asked problem).
*/
import { getEntry } from "astro:content";
import data from "blume:data";
import Badge from "blume/components/content/Badge.astro";
import { stripBase, withBase } from "blume/components/islands/base-path.ts";
import { APPENDIX } from "../appendix.ts";
import { 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";
@@ -46,6 +54,7 @@ const entry = at ? await getEntry(at.collection, at.entryId) : undefined;
const tags: TopicTag[] = entry?.data.topics ?? [];
const video: string | undefined = entry?.data.video;
const issue: string | undefined = entry?.data.issue;
const companies: Company[] = entry?.data.companies ?? [];
const served = new Set<string>(data.routes.map((r: { path: string }) => r.path));
@@ -96,6 +105,8 @@ const badges = tags.map((tag) => {
});
const linkClass = "no-underline transition-opacity hover:opacity-80";
// TypeTable's column track, so the header and every row align.
const columns = "grid grid-cols-[2fr_1fr_auto] items-center gap-4";
---
{
@@ -131,4 +142,34 @@ const linkClass = "no-underline transition-opacity hover:opacity-80";
)
}
{
companies.length > 0 && (
<div class="not-prose mb-6 rounded-blume border border-border bg-muted/30 p-1.5" data-blume-narration="skip">
<div class={`${columns} px-3 py-2 font-medium text-muted-foreground text-xs`}>
<span>Company</span>
<span>Asked within</span>
<span title="Relative within the company and window: 100 is its most-asked problem there">Frequency</span>
</div>
<div class="mt-1 flex flex-col">
{companies.map((c) => (
<div class={`${columns} border-border border-t px-3 py-2 text-xs`}>
<a href={withBase(companyHref(c.name))} class={linkClass}>
<Badge icon="building-2" shape="pill" stroke>
{c.name}
</Badge>
</a>
<span class="whitespace-nowrap text-foreground">{RECENCY_LABEL[c.period]}</span>
<span class="flex items-center gap-2">
<span class="h-1.5 w-16 overflow-hidden rounded-full bg-muted" aria-hidden="true">
<span class="block h-full rounded-full bg-accent" style={`width: ${c.frequency}%`} />
</span>
<code class="w-8 text-right font-mono text-foreground tabular-nums">{Math.round(c.frequency)}</code>
</span>
</div>
))}
</div>
</div>
)
}
<slot />