mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-10-25 09:43:20 +08:00
docs(kilo-docs): add sitemap.xml route
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/kilo-docs": patch
|
||||
---
|
||||
|
||||
Publish a sitemap at `/docs/sitemap.xml` so search engines can discover all documentation pages.
|
||||
@@ -0,0 +1,38 @@
|
||||
import { describe, it, expect } from "vitest"
|
||||
import { buildSitemapXml } from "../pages/api/sitemap.xml"
|
||||
|
||||
describe("sitemap.xml", () => {
|
||||
it("produces valid XML with urlset root", () => {
|
||||
const xml = buildSitemapXml()
|
||||
expect(xml).toMatch(/^<\?xml version="1\.0" encoding="UTF-8"\?>/)
|
||||
expect(xml).toContain('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">')
|
||||
expect(xml).toContain("</urlset>")
|
||||
})
|
||||
|
||||
it("all <loc> values start with https://kilo.ai/docs", () => {
|
||||
const xml = buildSitemapXml()
|
||||
const locs = [...xml.matchAll(/<loc>(.*?)<\/loc>/g)].map((m) => m[1])
|
||||
expect(locs.length).toBeGreaterThan(0)
|
||||
for (const loc of locs) {
|
||||
expect(loc).toMatch(/^https:\/\/kilo\.ai\/docs/)
|
||||
}
|
||||
})
|
||||
|
||||
it("includes the docs root URL", () => {
|
||||
const xml = buildSitemapXml()
|
||||
expect(xml).toContain("<loc>https://kilo.ai/docs</loc>")
|
||||
})
|
||||
|
||||
it("includes known pages from the nav", () => {
|
||||
const xml = buildSitemapXml()
|
||||
expect(xml).toContain("https://kilo.ai/docs/getting-started/installing")
|
||||
expect(xml).toContain("https://kilo.ai/docs/getting-started")
|
||||
})
|
||||
|
||||
it("has no duplicate <loc> entries", () => {
|
||||
const xml = buildSitemapXml()
|
||||
const locs = [...xml.matchAll(/<loc>(.*?)<\/loc>/g)].map((m) => m[1])
|
||||
const unique = new Set(locs)
|
||||
expect(locs.length).toBe(unique.size)
|
||||
})
|
||||
})
|
||||
@@ -30,6 +30,11 @@ module.exports = withMarkdoc(/* config: https://markdoc.io/docs/nextjs#options *
|
||||
source: "/llms.txt",
|
||||
destination: "/api/llms.txt",
|
||||
},
|
||||
{
|
||||
// Rewrite /docs/sitemap.xml to the API endpoint (internal to basePath)
|
||||
source: "/sitemap.xml",
|
||||
destination: "/api/sitemap.xml",
|
||||
},
|
||||
],
|
||||
afterFiles: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
import { Nav } from "../../lib/nav"
|
||||
import type { NavLink, NavSection } from "../../lib/types"
|
||||
|
||||
const origin = "https://kilo.ai"
|
||||
const base = "/docs"
|
||||
|
||||
function links(sections: NavSection[]): string[] {
|
||||
const out: string[] = []
|
||||
function walk(items: NavLink[]) {
|
||||
for (const item of items) {
|
||||
out.push(item.href)
|
||||
if (item.subLinks) walk(item.subLinks)
|
||||
}
|
||||
}
|
||||
for (const s of sections) walk(s.links)
|
||||
return out
|
||||
}
|
||||
|
||||
export function buildSitemapXml(): string {
|
||||
const all = Object.values(Nav).flatMap(links)
|
||||
const hrefs = Array.from(new Set(["", ...all])).sort()
|
||||
const urls = hrefs.map((h) => ` <url><loc>${origin}${base}${h}</loc></url>`).join("\n")
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
${urls}
|
||||
</urlset>`
|
||||
}
|
||||
|
||||
export default function handler(_: NextApiRequest, res: NextApiResponse) {
|
||||
const xml = buildSitemapXml()
|
||||
res.setHeader("Content-Type", "application/xml; charset=utf-8")
|
||||
res.setHeader("Cache-Control", "public, s-maxage=3600, stale-while-revalidate=86400")
|
||||
res.status(200).send(xml)
|
||||
}
|
||||
Reference in New Issue
Block a user