diff --git a/_components/Footer.tsx b/_components/Footer.tsx index 5365b3691..85a3b41e1 100644 --- a/_components/Footer.tsx +++ b/_components/Footer.tsx @@ -59,7 +59,7 @@ const data = [ }, { label: "Deno API Reference", - href: "/api/deno/~/Deno", + href: "/api/deno/", }, ], }, diff --git a/_components/SidebarNav/comp.tsx b/_components/SidebarNav/comp.tsx index f08f52d06..4e44d7c50 100644 --- a/_components/SidebarNav/comp.tsx +++ b/_components/SidebarNav/comp.tsx @@ -4,7 +4,7 @@ import ReferenceSidebarNav from "../../reference/_components/ReferenceSidebarNav export default function (data: Lume.Data) { const sectionData = data.sectionData; const currentUrl = data.currentUrl.replace(/\/$/, ""); - const isReference = currentUrl.startsWith("/api/"); + const isReference = currentUrl === "/api" || currentUrl.startsWith("/api/"); if (isReference) { return ; diff --git a/_includes/layout.tsx b/_includes/layout.tsx index f79bd04d7..b022c362b 100644 --- a/_includes/layout.tsx +++ b/_includes/layout.tsx @@ -148,7 +148,7 @@ export default function Layout(data: Lume.Data) { />
+
+

{data.title}

+

+ {data.aboutLabel} + {" ยท "} + All symbols +

+
+

+ {data.intro} +

+ + {data.groups.map(({ title, url, slug, group }) => ( +
+

+ + {title} + +

+
    + {group.sections.flatMap((section) => + section.nodes.map((node) => ( +
  • + + + {node.name} + + {node.docs && ( +
    + )} +
  • + )) + )} +
+
+ ))} + + ); +} diff --git a/_includes/reference/landing.tsx b/_includes/reference/landing.tsx new file mode 100644 index 000000000..84dcca9d5 --- /dev/null +++ b/_includes/reference/landing.tsx @@ -0,0 +1,86 @@ +export const layout = "doc.tsx"; + +export interface LandingTile { + title: string; + href: string; + description: string | null; +} + +export interface LandingSection { + key: string; + title: string; + description: string; + href: string; + allSymbolsHref: string; + tiles: LandingTile[]; + /** Render tiles in a denser grid (used for the long Node module list). */ + dense?: boolean; +} + +export interface LandingData { + intro: string; + sections: LandingSection[]; +} + +/** The /api/ hub: every API group presented as a tile grid, generated from + * the same grouping data as the reference pages themselves. */ +export default function ApiLanding( + { data }: { data: LandingData } & Lume.Data, + _helpers: Lume.Helpers, +) { + return ( +
+

API reference

+

{data.intro}

+ + {data.sections.map((section) => ( +
+
+

+ + {section.title} + +

+ + View all symbols + +
+

+ {section.description} +

+
+ {section.tiles.map((tile) => ( + + + {tile.title} + + {tile.description && ( + + {tile.description} + + )} + + ))} +
+
+ ))} +
+ ); +} diff --git a/_includes/reference/multiSymbol.tsx b/_includes/reference/multiSymbol.tsx new file mode 100644 index 000000000..088efd8ab --- /dev/null +++ b/_includes/reference/multiSymbol.tsx @@ -0,0 +1,52 @@ +import type { Group } from "../../reference/_lib/group.ts"; + +export const layout = "doc.tsx"; + +/** A grouped reference page: every symbol of a category (Deno, Web) or + * module (Node) documented on a single page โ€” a symbol index up top, + * full documentation below. */ +export default function MultiSymbol( + { data, comp }: { data: Group } & Lume.Data, + _helpers: Lume.Helpers, +) { + return ( + +
+
+

{data.title}

+ {data.docs &&
} + +
+ +
+ {data.sections.map((section) => ( +
+

{section.title}

+ +
+ ))} +
+ +
+ +
+ {data.symbols.map((symbol) => ( + + ))} +
+
+
+ ); +} + +function SymbolDivider( + // deno-lint-ignore no-explicit-any + { comp, symbol }: { comp: any; symbol: Group["symbols"][number] }, +) { + return ( + <> + +
+ + ); +} diff --git a/_includes/reference/preview.tsx b/_includes/reference/preview.tsx new file mode 100644 index 000000000..642292499 --- /dev/null +++ b/_includes/reference/preview.tsx @@ -0,0 +1,124 @@ +import type { + PreviewMember, + PreviewSymbol, +} from "../../reference/preview.page.ts"; + +export const layout = "doc.tsx"; + +interface PreviewData { + module: string; + usage: string; + symbols: PreviewSymbol[]; + kindOrder: string[]; + kindTitles: Record; +} + +/** PROTOTYPE layout: Node.js-docs-style prose-first rendering, fed from raw + * doc nodes instead of @deno/doc's pre-rendered HTML. */ +export default function Preview( + { data }: { data: PreviewData } & Lume.Data, + helpers: Lume.Helpers, +) { + const md = (text: string | null) => + text + ? ( +
+ ) + : null; + + const sinceBadge = (since: string | null) => + since && ( +

+ Added in: {since} +

+ ); + + const deprecatedBadge = (deprecated: string | null) => + deprecated !== null && ( +
+
Deprecated
+ {md(deprecated || "This API is deprecated.")} +
+ ); + + const member = (m: PreviewMember) => ( +
+

+ + {m.signature} + +

+ {sinceBadge(m.since)} + {m.returnType && ( +

+ Returns: {m.returnType} +

+ )} + {deprecatedBadge(m.deprecated)} + {md(m.doc)} +
+ ); + + return ( +
+
+

+ node:{data.module} +

+
+
Renderer preview
+

+ This page is a prototype of rendering reference docs directly from + raw doc nodes, side by side with{" "} + the current renderer. +

+
+
{data.usage}
+ + {data.kindOrder.map((kind) => { + const group = data.symbols.filter((s) => s.kind === kind); + if (group.length === 0) return null; + return ( +
+

+ {data.kindTitles[kind]} +

+ {group.map((symbol) => ( +
+

+ + {symbol.heading} + +

+ {sinceBadge(symbol.since)} + {symbol.signature && ( +
{symbol.signature}
+ )} + {symbol.returnType && symbol.kind !== "class" && ( +

+ {symbol.kind === "function" ? "Returns" : "Type"}:{" "} + {symbol.returnType} +

+ )} + {deprecatedBadge(symbol.deprecated)} + {md(symbol.doc)} + {symbol.members.map(member)} +
+ ))} +
+ ); + })} +
+
+ ); +} diff --git a/api/deno/index.md b/api/deno/index.md index 35572b869..e3557127a 100644 --- a/api/deno/index.md +++ b/api/deno/index.md @@ -2,6 +2,7 @@ title: "Deno Namespace APIs" description: "A guide to Deno's built-in runtime APIs. Learn about file system operations, network functionality, permissions management, and other core capabilities available through the global Deno namespace." layout: doc.tsx +url: /api/deno/about/ oldUrl: - /runtime/manual/runtime/ - /runtime/manual/runtime/builtin_apis/ diff --git a/api/node/index.md b/api/node/index.md index ac5afd6df..b7e497de6 100644 --- a/api/node/index.md +++ b/api/node/index.md @@ -2,6 +2,7 @@ title: "Node.js Built-in APIs" description: "Complete reference for Node.js built-in modules and globals supported in Deno. Explore Node.js APIs including fs, http, crypto, process, buffer, and more with compatibility information." layout: doc.tsx +url: /api/node/about/ oldUrl: - /runtime/manual/node/compatibility/ - /runtime/manual/npm_nodejs/compatibility_mode/ diff --git a/api/web/index.md b/api/web/index.md index a819cec84..1e9776794 100644 --- a/api/web/index.md +++ b/api/web/index.md @@ -2,6 +2,7 @@ title: "Web Platform APIs" description: "A guide to the Web Platform APIs available in Deno. Learn about fetch, events, workers, storage, and other web standard APIs, including implementation details and deviations from browser specifications." layout: doc.tsx +url: /api/web/about/ oldUrl: - /runtime/manual/runtime/navigator_api/ - /runtime/manual/runtime/web_platform_apis/ diff --git a/middleware/redirects.ts b/middleware/redirects.ts index 6a7f8af92..ab6d57655 100644 --- a/middleware/redirects.ts +++ b/middleware/redirects.ts @@ -140,6 +140,21 @@ function loadFromJson() { ); } + // Redirects from old per-symbol API reference URLs to their anchor on the + // grouped reference pages, generated by reference/reference.page.ts. + if (existsSync("./_site/api/_redirects.json")) { + const apiRedirects = JSON.parse( + new TextDecoder().decode( + Deno.readFileSync("./_site/api/_redirects.json"), + ), + ) as Record; + redirects = { ...apiRedirects, ...redirects }; + } else { + log.warn( + `๐Ÿ”— redirectsMiddleware: No './_site/api/_redirects.json' found.`, + ); + } + log.info( `๐Ÿ”— redirectsMiddleware: Total number of redirects loaded: ${ Object.keys(redirects).length @@ -154,8 +169,6 @@ function addGoLinksAndRedirectLinks(redirects: Record) { `๐Ÿ”— addGoLinksAndRedirectLinks: Adding additional redirects...`, ); - redirects["/api/"] = "/api/deno/"; - log.debug( `๐Ÿ”— redirectsMiddleware: Reading redirects from 'go.json'...`, ); diff --git a/orama/generate_orama_index_full.ts b/orama/generate_orama_index_full.ts index b9b70f1ab..4bd9039dc 100644 --- a/orama/generate_orama_index_full.ts +++ b/orama/generate_orama_index_full.ts @@ -16,6 +16,7 @@ import { walk } from "@std/fs"; import { fromFileUrl, join, relative } from "@std/path"; +import { buildReference } from "../reference/_lib/group.ts"; import { MarkdownIndexer } from "./indexing/MarkdownIndexer.ts"; import { FileSelector } from "./identification/FileSelector.ts"; import { IndexCollection } from "./indexing/IndexCollection.ts"; @@ -316,6 +317,8 @@ function processApiSymbol( async function processApiReference(): Promise { console.log("\n๐Ÿ”ง Processing API reference documentation..."); const apiDocs: OramaFullDocument[] = []; + // deno-lint-ignore no-explicit-any + const referenceJsons: Record = {}; for (const refFile of REFERENCE_FILES) { const fullPath = join(ROOT_DIR, refFile.path); @@ -326,6 +329,7 @@ async function processApiReference(): Promise { const content = await Deno.readTextFile(fullPath); const data = JSON.parse(content); + referenceJsons[refFile.apiType] = data; let processedCount = 0; let skippedCount = 0; @@ -362,6 +366,26 @@ async function processApiReference(): Promise { } } + // Symbols now live as anchors on grouped reference pages; remap the old + // per-symbol URLs so search results land directly on the right anchor. + if (referenceJsons.deno && referenceJsons.web && referenceJsons.node) { + try { + const { redirects } = buildReference(referenceJsons); + let remapped = 0; + for (const doc of apiDocs) { + const target = redirects[doc.path]; + if (target) { + doc.path = target; + doc.url = `${BASE_URL}${target}`; + remapped++; + } + } + console.log(` Remapped ${remapped} API doc URLs to grouped pages.`); + } catch (error) { + console.warn(`Could not remap API URLs to grouped pages: ${error}`); + } + } + return apiDocs; } diff --git a/reference/_components/ReferenceSidebarNav.tsx b/reference/_components/ReferenceSidebarNav.tsx index 635403572..c5f84629a 100644 --- a/reference/_components/ReferenceSidebarNav.tsx +++ b/reference/_components/ReferenceSidebarNav.tsx @@ -8,9 +8,8 @@ export default function ReferenceSidebarNav(data: Lume.Data) { title: "Deno APIs", key: "deno", basePath: "/api/deno", - categoryLabel: "Deno APIs by category", items: [ - { href: "/api/deno", title: "Deno specific APIs" }, + { href: "/api/deno/about/", title: "About", isBottom: true }, { href: "/api/deno/all_symbols", title: "All Deno symbols", @@ -22,9 +21,8 @@ export default function ReferenceSidebarNav(data: Lume.Data) { title: "Web APIs", key: "web", basePath: "/api/web", - categoryLabel: "Web APIs by category", items: [ - { href: "/api/web", title: "Web Platform Support" }, + { href: "/api/web/about/", title: "About", isBottom: true }, { href: "/api/web/all_symbols", title: "All web symbols", @@ -36,9 +34,8 @@ export default function ReferenceSidebarNav(data: Lume.Data) { title: "Node APIs", key: "node", basePath: "/api/node", - categoryLabel: "Node APIs by namespace", items: [ - { href: "/api/node", title: "Node support in deno" }, + { href: "/api/node/about/", title: "About", isBottom: true }, { href: "/api/node/all_symbols", title: "All node symbols", @@ -87,7 +84,11 @@ function ApiSection({ section, currentUrl, apiCategories }: { return (