/** * LeetCode topic-tag slug → the campaign landing routes that teach it, in * default preference order. The one answer to "does the campaign cover this * tag", read by the sides that must agree: * * - `components/ProblemBadges.astro` links a covered tag's badge to its * landing page, and every other tag's badge to its Appendix card, * `/appendix#` (`appendix.ts`); * - `components/BacklinksList.astro` lists, under a landing page, every * problem whose badge links there — both via `tagTarget()`; * - `apps/cli/sync.ts` warns about a tag a problem page carries that is * neither a key here nor an Appendix term. * * Add a key when a campaign topic starts teaching a tag; its Appendix term is * then dead weight, delete it. A tag naming two topics (DFS/BFS: tree and * graph; DP: 1-D and grid) lists both; the badge picks per page. */ import { APPENDIX } from "./appendix.ts"; export const TOPIC_LANDINGS: Record = { "hash-table": ["/hash-table"], "prefix-sum": ["/prefix-sum"], "two-pointers": ["/two-pointers"], "sliding-window": ["/sliding-window"], "binary-search": ["/binary-search"], stack: ["/stack"], "monotonic-stack": ["/monotonic-stack"], "linked-list": ["/linked-list"], matrix: ["/matrix-index-math"], "depth-first-search": ["/tree-dfs", "/graph-dfs"], "breadth-first-search": ["/tree-bfs", "/graph-bfs"], "binary-search-tree": ["/binary-search-tree"], "heap-priority-queue": ["/heap-priority-queue"], trie: ["/trie"], "topological-sort": ["/topological-sort"], "union-find": ["/union-find"], backtracking: ["/backtracking"], "dynamic-programming": ["/1d-dynamic-programming", "/multi-d-grid-dp"], greedy: ["/greedy"], }; /** One of LeetCode's topic tags, as a problem page's `topics:` frontmatter carries it. */ export interface TopicTag { name: string; slug: string; } /** * Where a problem page's badge for `tag` points: a root-relative landing * route or Appendix anchor (the caller adds the base), or LeetCode's problem * list when the site has neither, so a badge never links to a 404. * * A tag naming two landings links to the page's own topic — its route's first * segment — when that is one of them; otherwise DFS/BFS prefer the tree topic * for a problem LeetCode also tags `Tree` and the graph topic for the rest. */ export function tagTarget( tag: TopicTag, page: { route: string; tags: readonly TopicTag[] }, served: ReadonlySet, ): { href: string; kind: "landing" | "appendix" | "external" } { const landings = (TOPIC_LANDINGS[tag.slug] ?? []).filter((path) => served.has(path)); const own = `/${page.route.split("/")[1]}`; const prefer = page.tags.some((t) => t.slug === "tree") ? "/tree-" : "/graph-"; const landing = landings.includes(own) ? own : (landings.find((p) => p.startsWith(prefer)) ?? landings[0]); if (landing) return { href: landing, kind: "landing" }; if (APPENDIX[tag.slug]) return { href: `/appendix#${tag.slug}`, kind: "appendix" }; return { href: `https://leetcode.com/problem-list/${tag.slug}/`, kind: "external" }; }