Files
vue-journal-layer/app/utils/sitemap.ts
Jakub Zych 783426c5d8 feat: Journal author and tag pages, SEO, sitemap source and RSS route
- author pages resolve slug or login and canonicalise to the slug
- tag pages, per-page SEO meta and canonicals that keep ?page=N
- sitemap source pages the API and builds locs from journal.routes
- /rss.xml proxies the API feed with x-forwarded-for
- neutral README; version 0.1.0
2026-10-09 18:06:20 +02:00

41 lines
1.3 KiB
TypeScript

// Sitemap entries for Journal content. Every loc is built from journal.routes,
// so moving or disabling a view moves or drops its URLs; nothing hard-codes
// a path.
import { flattenCategories } from './client.ts'
import { fillJournalPath } from './routes.ts'
import type { JournalCategory, JournalPost, JournalRoutes } from './types.ts'
export interface JournalSitemapEntry {
loc: string
lastmod?: string
}
/**
* One entry per published post (lastmod = updated_at) at routes.post, and one
* per category of the flattened tree at routes.category. A disabled route
* contributes nothing.
*/
export function buildJournalSitemapEntries(
posts: readonly JournalPost[],
categories: readonly JournalCategory[],
routes: JournalRoutes,
): JournalSitemapEntry[] {
const entries: JournalSitemapEntry[] = []
if (routes.post !== false) {
for (const post of posts) {
if (!post.published || !post.slug) continue
const entry: JournalSitemapEntry = { loc: fillJournalPath(routes.post, { slug: post.slug }) }
if (post.updated_at) entry.lastmod = post.updated_at
entries.push(entry)
}
}
if (routes.category !== false) {
for (const category of flattenCategories(categories)) {
if (!category.slug) continue
entries.push({ loc: fillJournalPath(routes.category, { category: category.slug }) })
}
}
return entries
}