livemark 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/SidebarPosts.js +4 -4
- package/build/helpers/rss.d.ts +21 -0
- package/build/helpers/rss.js +56 -0
- package/build/helpers/rss.unit.d.ts +1 -0
- package/build/helpers/rss.unit.js +123 -0
- package/build/plugins/vite-robots.d.ts +17 -0
- package/build/plugins/vite-robots.js +40 -0
- package/build/plugins/vite-robots.unit.d.ts +1 -0
- package/build/plugins/vite-robots.unit.js +20 -0
- package/build/routeTree.gen.d.ts +16 -3
- package/build/routeTree.gen.js +8 -1
- package/build/routes/$section.rss[.]xml.d.ts +7 -0
- package/build/routes/$section.rss[.]xml.js +56 -0
- package/build/routes/__root.js +12 -1
- package/build/vite.config.js +19 -2
- package/package.json +14 -15
- package/source/components/SidebarPosts.tsx +12 -6
- package/source/helpers/rss.ts +80 -0
- package/source/helpers/rss.unit.ts +134 -0
- package/source/plugins/vite-robots.ts +51 -0
- package/source/plugins/vite-robots.unit.ts +32 -0
- package/source/routeTree.gen.ts +21 -3
- package/source/routes/$section.rss[.]xml.tsx +60 -0
- package/source/routes/__root.tsx +11 -0
- package/source/vite.config.ts +19 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { config } from "livemark:virtual"
|
|
2
|
+
import { createFileRoute } from "@tanstack/react-router"
|
|
3
|
+
import { sectionFlatArticles, sortedArticles } from "../content/article.ts"
|
|
4
|
+
import { renderRssFeed, type RssItem } from "../helpers/rss.ts"
|
|
5
|
+
|
|
6
|
+
const FEED_ITEM_LIMIT = 20
|
|
7
|
+
|
|
8
|
+
export const Route = createFileRoute("/$section/rss.xml")({
|
|
9
|
+
server: {
|
|
10
|
+
handlers: {
|
|
11
|
+
GET: async ({ params }: { params: { section: string } }) => {
|
|
12
|
+
if (!config.site) {
|
|
13
|
+
return new Response("RSS requires `site` in livemark.config.ts", {
|
|
14
|
+
status: 404,
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
const prefix = `/${params.section}/`
|
|
18
|
+
const section = config.sections?.find(
|
|
19
|
+
s => s.type === "blog" && s.prefix === prefix,
|
|
20
|
+
)
|
|
21
|
+
if (!section || section.type !== "blog") {
|
|
22
|
+
return new Response("Not found", { status: 404 })
|
|
23
|
+
}
|
|
24
|
+
const host = config.site.replace(/\/+$/, "")
|
|
25
|
+
const base = config.base ?? ""
|
|
26
|
+
const toAbsolute = (path: string) => `${host}${base}${path}`
|
|
27
|
+
|
|
28
|
+
const paths = sectionFlatArticles.get(section.prefix) ?? []
|
|
29
|
+
const items: RssItem[] = []
|
|
30
|
+
for (const path of paths) {
|
|
31
|
+
if (items.length >= FEED_ITEM_LIMIT) break
|
|
32
|
+
const article = sortedArticles.find(a => a.path === path)
|
|
33
|
+
if (!article?.date) continue
|
|
34
|
+
const link = toAbsolute(article.path)
|
|
35
|
+
items.push({
|
|
36
|
+
title: article.title,
|
|
37
|
+
link,
|
|
38
|
+
guid: link,
|
|
39
|
+
description: article.description,
|
|
40
|
+
pubDate: article.date,
|
|
41
|
+
author: article.author,
|
|
42
|
+
categories: article.tags,
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const xml = renderRssFeed({
|
|
47
|
+
title: section.siteTitle ?? section.title,
|
|
48
|
+
description: section.siteDescription ?? config.description ?? "",
|
|
49
|
+
link: toAbsolute(section.prefix),
|
|
50
|
+
feedLink: toAbsolute(`${section.prefix}rss.xml`),
|
|
51
|
+
items,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
return new Response(xml, {
|
|
55
|
+
headers: { "Content-Type": "application/rss+xml; charset=utf-8" },
|
|
56
|
+
})
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
})
|
package/source/routes/__root.tsx
CHANGED
|
@@ -26,6 +26,16 @@ export const Route = createRootRoute({
|
|
|
26
26
|
config.favicon ?? config.logo ?? defaultFavicon,
|
|
27
27
|
config.base,
|
|
28
28
|
)
|
|
29
|
+
const feedLinks = config.site
|
|
30
|
+
? (config.sections ?? [])
|
|
31
|
+
.filter(s => s.type === "blog")
|
|
32
|
+
.map(s => ({
|
|
33
|
+
rel: "alternate",
|
|
34
|
+
type: "application/rss+xml",
|
|
35
|
+
title: `${s.siteTitle ?? s.title} RSS Feed`,
|
|
36
|
+
href: prefixUrl(`${s.prefix}rss.xml`, config.base),
|
|
37
|
+
}))
|
|
38
|
+
: []
|
|
29
39
|
return {
|
|
30
40
|
meta: [
|
|
31
41
|
{ charSet: "utf-8" },
|
|
@@ -48,6 +58,7 @@ export const Route = createRootRoute({
|
|
|
48
58
|
{ rel: "shortcut icon", href: favicon, type: faviconType(favicon) },
|
|
49
59
|
{ rel: "stylesheet", href: generalCss },
|
|
50
60
|
{ rel: "stylesheet", href: markdownCss },
|
|
61
|
+
...feedLinks,
|
|
51
62
|
],
|
|
52
63
|
}
|
|
53
64
|
},
|
package/source/vite.config.ts
CHANGED
|
@@ -7,12 +7,27 @@ import { defineConfig } from "vite"
|
|
|
7
7
|
import svgr from "vite-plugin-svgr"
|
|
8
8
|
import { loadConfig } from "./actions/config/load.ts"
|
|
9
9
|
import { livemark } from "./plugins/vite-livemark.ts"
|
|
10
|
+
import { robots } from "./plugins/vite-robots.ts"
|
|
10
11
|
|
|
11
12
|
const config = await loadConfig()
|
|
12
13
|
|
|
14
|
+
// Per-blog-section RSS feed paths to prerender. Gated on `config.site`
|
|
15
|
+
// because feed URLs are absolute (matching the sitemap/robots.txt gate)
|
|
16
|
+
// and the route returns 404 without it anyway. Excluded from the sitemap
|
|
17
|
+
// since `.xml` payloads don't belong in a sitemap.
|
|
18
|
+
const blogFeedPages = config.site
|
|
19
|
+
? (config.sections ?? [])
|
|
20
|
+
.filter(s => s.type === "blog")
|
|
21
|
+
.map(s => ({
|
|
22
|
+
path: `${config.base ?? ""}${s.prefix}rss.xml`,
|
|
23
|
+
sitemap: { exclude: true },
|
|
24
|
+
}))
|
|
25
|
+
: []
|
|
26
|
+
|
|
13
27
|
export default defineConfig({
|
|
14
28
|
plugins: [
|
|
15
29
|
livemark({ config }),
|
|
30
|
+
robots({ config }),
|
|
16
31
|
devtools(),
|
|
17
32
|
tailwind(),
|
|
18
33
|
contentCollections({ configPath: "content-collections.ts" }),
|
|
@@ -21,7 +36,10 @@ export default defineConfig({
|
|
|
21
36
|
// Seed path must match what the crawler produces (router-emitted
|
|
22
37
|
// hrefs include the basepath), otherwise prerender records both
|
|
23
38
|
// shapes and the sitemap ends up with duplicate entries.
|
|
24
|
-
pages: [
|
|
39
|
+
pages: [
|
|
40
|
+
{ path: config.base ? `${config.base}/` : "/" },
|
|
41
|
+
...blogFeedPages,
|
|
42
|
+
],
|
|
25
43
|
// Disable route-tree auto-discovery: it produces basepath-naive
|
|
26
44
|
// paths (e.g. `/`) that duplicate the crawl-derived prefixed paths,
|
|
27
45
|
// bloating pages.json and sitemap. Crawling from the seed already
|