// c32 — pure logic: given a (section, slug) tuple from a /edit/<...> // URL, resolve it to the editable resource (page URL, file path on // disk, page title) — or return null if the combination doesn't map // to an existing doc page. Pure: no I/O. The handler does the actual // fs read for the current body. // // Editable sections are the ones that already have a registry: sama, // guides, blog. Slug must match an entry in the corresponding registry // — this prevents arbitrary file writes via /edit/../../etc/passwd // style inputs. import { ALL_SAMA } from "./a31_sama.ts"; import { ALL_GUIDES } from "./a31_guides.ts"; import { ALL_POSTS } from "./a31_blog.ts"; import { SITE_NAV } from "./a31_docs_nav.ts"; export type EditableSection = "sama" | "guides" | "blog"; export interface ResolvedEdit { section: EditableSection; slug: string; pageUrl: string; filePath: string; title: string; } const SECTIONS = new Set(["sama", "guides", "blog"]); const isValidSection = (s: string): s is EditableSection => SECTIONS.has(s as EditableSection); const SAFE_SLUG = /^[a-z0-9][a-z0-9-]*$/; const lookupTitle = (section: EditableSection, slug: string): string | null => { if (section === "sama") { const e = ALL_SAMA.find((d) => d.slug === slug); if (e) return `${e.letter} — ${e.title}`; } else if (section === "guides") { const e = ALL_GUIDES.find((g) => g.slug === slug); if (e) return e.title; } else { const e = ALL_POSTS.find((p) => p.slug === slug); if (e) return e.title; } // Fallback to SITE_NAV: nav-only editable pages (e.g. /sama/skill) // have a content/<...>.md backing file but no entry in the discipline // / guide / blog registries. They're listed in SITE_NAV with a // non-null editPath, which is the single source of truth for // "this docs page is editable". const navSection = SITE_NAV.find((s) => s.id === section); const link = navSection?.links.find( (l) => l.href === `/${section}/${slug}` && l.editPath !== null, ); return link?.label ?? null; }; export const resolveEdit = (section: string, slug: string): ResolvedEdit | null => { if (!isValidSection(section)) return null; if (!SAFE_SLUG.test(slug)) return null; const title = lookupTitle(section, slug); if (title === null) return null; // /sama discipline pages live under /sama/discipline/ as of // PR #53. /blog pages live under /blog// as of PR #55. // Other sections keep the flat /
/ shape. let pageUrl: string; if (section === "sama" && slug !== "skill" && slug !== "v2") { pageUrl = `/sama/discipline/${slug}`; } else if (section === "blog") { const post = ALL_POSTS.find((p) => p.slug === slug); pageUrl = post ? `/blog/${post.date.slice(0, 7)}/${slug}` : `/blog/${slug}`; } else { pageUrl = `/${section}/${slug}`; } return { section, slug, pageUrl, filePath: `content/${section}/${slug}.md`, title, }; };