|
| 1 | +import fs from "node:fs/promises"; |
| 2 | +import path from "node:path"; |
| 3 | +import type { MetadataRoute } from "next"; |
| 4 | + |
| 5 | +const SITE_URL = process.env.SITE_URL ?? "https://docs.arcade.dev"; |
| 6 | +const NORMALIZED_SITE_URL = SITE_URL.replace(/\/+$/, ""); |
| 7 | +const APP_DIR = path.join(process.cwd(), "app"); |
| 8 | +const SKIP_DIRS = new Set(["_meta", "_api", "_redirects", "api"]); |
| 9 | +const INDEX_SUFFIX_REGEX = /\/index$/; |
| 10 | +let cachedRoutes: Promise<MetadataRoute.Sitemap> | null = null; |
| 11 | + |
| 12 | +async function collectRoutes(dir: string): Promise<MetadataRoute.Sitemap> { |
| 13 | + const dirs = await fs.readdir(dir, { withFileTypes: true }); |
| 14 | + const entries: MetadataRoute.Sitemap = []; |
| 15 | + |
| 16 | + for (const entry of dirs) { |
| 17 | + if (entry.isDirectory()) { |
| 18 | + if (SKIP_DIRS.has(entry.name) || entry.name.includes("[")) { |
| 19 | + continue; |
| 20 | + } |
| 21 | + const childRoutes = await collectRoutes(path.join(dir, entry.name)); |
| 22 | + entries.push(...childRoutes); |
| 23 | + continue; |
| 24 | + } |
| 25 | + |
| 26 | + if (entry.isFile() && entry.name === "page.mdx") { |
| 27 | + const filePath = path.join(dir, entry.name); |
| 28 | + const stats = await fs.stat(filePath); |
| 29 | + |
| 30 | + const relativeDir = path |
| 31 | + .relative(APP_DIR, dir) |
| 32 | + .replace(/\\/g, "/") |
| 33 | + .replace(INDEX_SUFFIX_REGEX, ""); |
| 34 | + |
| 35 | + const routePath = relativeDir ? `/${relativeDir}` : "/"; |
| 36 | + entries.push({ |
| 37 | + url: `${NORMALIZED_SITE_URL}${routePath}`, |
| 38 | + lastModified: stats.mtime, |
| 39 | + }); |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + return entries; |
| 44 | +} |
| 45 | + |
| 46 | +export default function sitemap(): Promise<MetadataRoute.Sitemap> { |
| 47 | + if (!cachedRoutes) { |
| 48 | + cachedRoutes = collectRoutes(APP_DIR).then((routes) => { |
| 49 | + routes.sort((a, b) => a.url.localeCompare(b.url)); |
| 50 | + return routes; |
| 51 | + }); |
| 52 | + } |
| 53 | + |
| 54 | + return cachedRoutes; |
| 55 | +} |
0 commit comments