2026-09-28 11:20:41 -04:00
|
|
|
/**
|
|
|
|
|
* LeetCode topic-tag slug → the campaign landing routes that teach it, in
|
|
|
|
|
* default preference order. The one answer to "does the campaign cover this
|
2026-09-29 15:12:54 -04:00
|
|
|
* tag", read by the sides that must agree:
|
2026-09-28 11:20:41 -04:00
|
|
|
*
|
|
|
|
|
* - `components/ProblemBadges.astro` links a covered tag's badge to its
|
2026-10-05 12:34:34 -04:00
|
|
|
* landing page, and every other tag's badge to its Appendix card,
|
|
|
|
|
* `/appendix#<slug>` (`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.
|
2026-09-28 11:20:41 -04:00
|
|
|
*
|
2026-10-05 12:34:34 -04:00
|
|
|
* 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
|
2026-09-28 11:20:41 -04:00
|
|
|
* graph; DP: 1-D and grid) lists both; the badge picks per page.
|
|
|
|
|
*/
|
2026-10-05 12:34:34 -04:00
|
|
|
import { APPENDIX } from "./appendix.ts";
|
|
|
|
|
|
2026-09-28 11:20:41 -04:00
|
|
|
export const TOPIC_LANDINGS: Record<string, readonly string[]> = {
|
|
|
|
|
"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"],
|
|
|
|
|
};
|
2026-09-29 15:12:54 -04:00
|
|
|
|
|
|
|
|
/** One of LeetCode's topic tags, as a problem page's `topics:` frontmatter carries it. */
|
|
|
|
|
export interface TopicTag {
|
|
|
|
|
name: string;
|
|
|
|
|
slug: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-10-05 12:34:34 -04:00
|
|
|
* 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.
|
2026-09-29 15:12:54 -04:00
|
|
|
*
|
|
|
|
|
* 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<string>,
|
2026-10-05 12:34:34 -04:00
|
|
|
): { href: string; kind: "landing" | "appendix" | "external" } {
|
2026-09-29 15:12:54 -04:00
|
|
|
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" };
|
2026-10-05 12:34:34 -04:00
|
|
|
if (APPENDIX[tag.slug]) return { href: `/appendix#${tag.slug}`, kind: "appendix" };
|
2026-09-29 15:12:54 -04:00
|
|
|
return { href: `https://leetcode.com/problem-list/${tag.slug}/`, kind: "external" };
|
|
|
|
|
}
|