@levino/shipyard-blog 0.7.4 → 0.7.5

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.
@@ -1,69 +1,36 @@
1
1
  ---
2
2
  import { Image } from 'astro:assets'
3
3
  import { i18n } from 'astro:config/server'
4
- import { getCollection } from 'astro:content'
5
- import blogConfig from 'virtual:shipyard-blog/config'
6
- import type { GetStaticPaths } from 'astro'
4
+ import { type CollectionKey, getCollection } from 'astro:content'
5
+ import blogConfigDefault from 'virtual:shipyard-blog/config'
7
6
  import Layout from './Layout.astro'
8
7
 
9
- const { postsPerPage, routeBasePath } = blogConfig
10
-
11
- export const getStaticPaths = (async () => {
12
- const allPosts = await getCollection('blog')
13
-
14
- if (i18n) {
15
- const paths: Array<{ params: { locale: string; page: string } }> = []
16
-
17
- for (const locale of i18n.locales) {
18
- if (typeof locale !== 'string') {
19
- throw new Error('shipyard does only support strings as locales.')
20
- }
21
-
22
- const localePosts = allPosts.filter(({ id }) => {
23
- const [postLocale] = id.split('/')
24
- return postLocale === locale
25
- })
26
-
27
- const totalPages = Math.ceil(localePosts.length / blogConfig.postsPerPage)
28
-
29
- // Generate pages 2+ only (page 1 is handled by BlogIndex.astro)
30
- for (let pageNum = 2; pageNum <= totalPages; pageNum++) {
31
- paths.push({ params: { locale, page: String(pageNum) } })
32
- }
33
- }
8
+ const blogConfig = Astro.props.blogConfig ?? blogConfigDefault
9
+ const collectionName =
10
+ Astro.props.collectionName ?? blogConfigDefault.collectionName
34
11
 
35
- return paths
36
- } else {
37
- const totalPages = Math.ceil(allPosts.length / blogConfig.postsPerPage)
38
- const paths: Array<{ params: { page: string } }> = []
39
-
40
- // Generate pages 2+ only
41
- for (let pageNum = 2; pageNum <= totalPages; pageNum++) {
42
- paths.push({ params: { page: String(pageNum) } })
43
- }
44
-
45
- return paths
46
- }
47
- }) satisfies GetStaticPaths
12
+ const { postsPerPage, routeBasePath } = blogConfig
48
13
 
49
14
  // Get current page from URL params
50
15
  const pageParam = Astro.params.page
51
16
  const currentPage = parseInt(pageParam, 10)
52
17
 
53
- const entries = await getCollection('blog').then((posts) => {
54
- if (i18n) {
55
- return posts
56
- .filter(({ id }) => {
57
- const [postLocale] = id.split('/')
58
- return postLocale === Astro.currentLocale
59
- })
60
- .toSorted((a, b) => b.data.date.getTime() - a.data.date.getTime())
61
- } else {
62
- return posts.toSorted(
63
- (a, b) => b.data.date.getTime() - a.data.date.getTime(),
64
- )
65
- }
66
- })
18
+ const entries = await getCollection(collectionName as CollectionKey).then(
19
+ (posts) => {
20
+ if (i18n) {
21
+ return posts
22
+ .filter(({ id }) => {
23
+ const [postLocale] = id.split('/')
24
+ return postLocale === Astro.currentLocale
25
+ })
26
+ .toSorted((a, b) => b.data.date.getTime() - a.data.date.getTime())
27
+ } else {
28
+ return posts.toSorted(
29
+ (a, b) => b.data.date.getTime() - a.data.date.getTime(),
30
+ )
31
+ }
32
+ },
33
+ )
67
34
 
68
35
  // Calculate pagination
69
36
  const totalPosts = entries.length
@@ -114,7 +81,7 @@ const showRightEllipsis =
114
81
  adjacentPages[adjacentPages.length - 1] < totalPages - 1
115
82
  ---
116
83
 
117
- <Layout title="Blog">
84
+ <Layout title="Blog" blogConfig={blogConfig} collectionName={collectionName}>
118
85
  <div class="max-w-7xl mx-auto">
119
86
  <div class="space-y-6">
120
87
  {
@@ -3,78 +3,29 @@
3
3
  * Individual tag page - shows all posts with a specific tag.
4
4
  */
5
5
  import { i18n } from 'astro:config/server'
6
- import { type CollectionEntry, getCollection } from 'astro:content'
7
- import blogConfig from 'virtual:shipyard-blog/config'
8
- import tagsMap from 'virtual:shipyard-blog/tags'
9
- import type { GetStaticPaths } from 'astro'
10
6
  import {
11
- filter,
12
- includes,
13
- map,
14
- pipe,
15
- reverse,
16
- sortBy,
17
- toLower,
18
- uniq,
19
- } from 'ramda'
7
+ type CollectionEntry,
8
+ type CollectionKey,
9
+ getCollection,
10
+ } from 'astro:content'
11
+ import blogConfigDefault from 'virtual:shipyard-blog/config'
12
+ import tagsMapDefault from 'virtual:shipyard-blog/tags'
13
+ import { filter, includes, map, pipe, reverse, sortBy, toLower } from 'ramda'
20
14
  import { getReadingTime, getTagDescription, getTagLabel } from '../src/index'
21
15
  import BlogReadingTime from './BlogReadingTime.astro'
22
16
  import BlogTags from './BlogTags.astro'
23
17
  import Layout from './Layout.astro'
24
18
 
25
- export const getStaticPaths = (async () => {
26
- const allPosts = await getCollection('blog')
27
- const { includeDraftsInDev } = blogConfig
28
- const isDev = import.meta.env.DEV
29
-
30
- // Filter out draft and unlisted posts - defined inside getStaticPaths
31
- const shouldIncludePost = (post: CollectionEntry<'blog'>) => {
32
- if (post.data.unlisted) return false
33
- if (post.data.draft && !(isDev && includeDraftsInDev)) return false
34
- return true
35
- }
36
-
37
- // Get all unique tags across all posts
38
- const getAllTags = pipe(
39
- filter(shouldIncludePost),
40
- (posts: CollectionEntry<'blog'>[]) =>
41
- posts.flatMap((post) => post.data.tags ?? []),
42
- map(toLower),
43
- uniq,
44
- ) as (posts: CollectionEntry<'blog'>[]) => string[]
45
-
46
- const allTags = getAllTags(allPosts)
47
-
48
- if (i18n) {
49
- // Generate paths for each locale + tag combination
50
- const paths: Array<{ params: { locale: string; tag: string } }> = []
51
-
52
- for (const locale of i18n.locales) {
53
- if (typeof locale !== 'string') continue
54
-
55
- // Get tags for this locale's posts
56
- const localePosts = allPosts.filter((post) => {
57
- const [postLocale] = post.id.split('/')
58
- return postLocale === locale
59
- })
60
- const localeTags = getAllTags(localePosts)
61
-
62
- for (const tag of localeTags) {
63
- paths.push({ params: { locale, tag } })
64
- }
65
- }
66
-
67
- return paths
68
- } else {
69
- return allTags.map((tag) => ({ params: { tag } }))
70
- }
71
- }) satisfies GetStaticPaths
19
+ const blogConfig = Astro.props.blogConfig ?? blogConfigDefault
20
+ const collectionName =
21
+ Astro.props.collectionName ?? blogConfigDefault.collectionName
22
+ const tagsMap = Astro.props.tagsMap ?? tagsMapDefault
72
23
 
73
24
  const { includeDraftsInDev, showReadingTime, routeBasePath } = blogConfig
74
25
 
75
26
  // Filter out draft and unlisted posts for runtime use
76
27
  const isDev = import.meta.env.DEV
77
- const shouldIncludePost = (post: CollectionEntry<'blog'>) => {
28
+ const shouldIncludePost = (post: CollectionEntry<CollectionKey>) => {
78
29
  if (post.data.unlisted) return false
79
30
  if (post.data.draft && !(isDev && includeDraftsInDev)) return false
80
31
  return true
@@ -82,10 +33,10 @@ const shouldIncludePost = (post: CollectionEntry<'blog'>) => {
82
33
 
83
34
  const { tag } = Astro.params
84
35
 
85
- const allPosts = await getCollection('blog')
36
+ const allPosts = await getCollection(collectionName as CollectionKey)
86
37
  const posts = pipe(
87
38
  filter(shouldIncludePost),
88
- filter((post: CollectionEntry<'blog'>) => {
39
+ filter((post: CollectionEntry<CollectionKey>) => {
89
40
  // Filter by locale if i18n is enabled
90
41
  if (i18n) {
91
42
  const [postLocale] = post.id.split('/')
@@ -95,9 +46,9 @@ const posts = pipe(
95
46
  const postTags = post.data.tags ?? []
96
47
  return includes(tag.toLowerCase(), map(toLower, postTags))
97
48
  }),
98
- sortBy((post: CollectionEntry<'blog'>) => post.data.date.getTime()),
49
+ sortBy((post: CollectionEntry<CollectionKey>) => post.data.date.getTime()),
99
50
  reverse,
100
- )(allPosts) as CollectionEntry<'blog'>[]
51
+ )(allPosts) as CollectionEntry<CollectionKey>[]
101
52
 
102
53
  const formatDate = new Intl.DateTimeFormat(Astro.currentLocale || 'en', {
103
54
  year: 'numeric',
@@ -122,7 +73,7 @@ const tagLabel = getTagLabel(tagsMap, tag)
122
73
  const tagDescription = getTagDescription(tagsMap, tag)
123
74
  ---
124
75
 
125
- <Layout title={`Posts tagged "${tagLabel}"`}>
76
+ <Layout title={`Posts tagged "${tagLabel}"`} blogConfig={blogConfig} collectionName={collectionName}>
126
77
  <div class="max-w-4xl mx-auto">
127
78
  <div class="mb-8">
128
79
  <a
@@ -3,38 +3,33 @@
3
3
  * Blog tags index page - lists all tags with post counts.
4
4
  */
5
5
  import { i18n } from 'astro:config/server'
6
- import { type CollectionEntry, getCollection } from 'astro:content'
7
- import blogConfig from 'virtual:shipyard-blog/config'
8
- import tagsMap from 'virtual:shipyard-blog/tags'
9
- import type { GetStaticPaths } from 'astro'
6
+ import {
7
+ type CollectionEntry,
8
+ type CollectionKey,
9
+ getCollection,
10
+ } from 'astro:content'
11
+ import blogConfigDefault from 'virtual:shipyard-blog/config'
12
+ import tagsMapDefault from 'virtual:shipyard-blog/tags'
10
13
  import { groupBy, map, pipe, prop, reverse, sortBy, toPairs } from 'ramda'
11
14
  import { getTagDescription, getTagLabel, getTagPermalink } from '../src/index'
12
15
  import Layout from './Layout.astro'
13
16
 
17
+ const blogConfig = Astro.props.blogConfig ?? blogConfigDefault
18
+ const collectionName =
19
+ Astro.props.collectionName ?? blogConfigDefault.collectionName
20
+ const tagsMap = Astro.props.tagsMap ?? tagsMapDefault
21
+
14
22
  const { includeDraftsInDev, routeBasePath } = blogConfig
15
23
 
16
24
  // Filter out draft and unlisted posts
17
25
  const isDev = import.meta.env.DEV
18
- const shouldIncludePost = (post: CollectionEntry<'blog'>) => {
26
+ const shouldIncludePost = (post: CollectionEntry<CollectionKey>) => {
19
27
  if (post.data.unlisted) return false
20
28
  if (post.data.draft && !(isDev && includeDraftsInDev)) return false
21
29
  return true
22
30
  }
23
31
 
24
- export const getStaticPaths = (() => {
25
- if (i18n) {
26
- return i18n.locales.map((locale) => {
27
- if (typeof locale !== 'string') {
28
- throw new Error('shipyard does only support strings as locales.')
29
- }
30
- return { params: { locale } }
31
- })
32
- } else {
33
- return [{ params: {} }]
34
- }
35
- }) satisfies GetStaticPaths
36
-
37
- const allPosts = await getCollection('blog')
32
+ const allPosts = await getCollection(collectionName as CollectionKey)
38
33
  const posts = allPosts.filter(shouldIncludePost).filter(({ id }) => {
39
34
  if (i18n) {
40
35
  const [postLocale] = id.split('/')
@@ -47,7 +42,7 @@ const posts = allPosts.filter(shouldIncludePost).filter(({ id }) => {
47
42
  type TagCount = { tag: string; count: number }
48
43
 
49
44
  const getTagCounts = pipe(
50
- (posts: CollectionEntry<'blog'>[]) =>
45
+ (posts: CollectionEntry<CollectionKey>[]) =>
51
46
  posts.flatMap((post) => post.data.tags ?? []),
52
47
  groupBy((tag: string) => tag.toLowerCase()),
53
48
  map((tags: string[]) => tags.length),
@@ -55,7 +50,7 @@ const getTagCounts = pipe(
55
50
  map(([tag, count]): TagCount => ({ tag, count: count as number })),
56
51
  sortBy(prop('count')),
57
52
  reverse,
58
- ) as (posts: CollectionEntry<'blog'>[]) => TagCount[]
53
+ ) as (posts: CollectionEntry<CollectionKey>[]) => TagCount[]
59
54
 
60
55
  const tagCounts = getTagCounts(posts)
61
56
 
@@ -76,7 +71,7 @@ const tagCountsWithMeta = tagCounts.map(({ tag, count }) => ({
76
71
  }))
77
72
  ---
78
73
 
79
- <Layout title="Tags">
74
+ <Layout title="Tags" blogConfig={blogConfig} collectionName={collectionName}>
80
75
  <div class="max-w-4xl mx-auto">
81
76
  <h1 class="text-4xl font-bold mb-8">Tags</h1>
82
77
 
@@ -1,21 +1,28 @@
1
1
  ---
2
2
  import { i18n } from 'astro:config/server'
3
- import { getCollection } from 'astro:content'
4
- import blogConfig from 'virtual:shipyard-blog/config'
3
+ import { type CollectionKey, getCollection } from 'astro:content'
4
+ import blogConfigDefault from 'virtual:shipyard-blog/config'
5
5
  import type { NavigationTree } from '@levino/shipyard-base'
6
6
  import { Page as BaseLayout } from '@levino/shipyard-base/layouts'
7
+ import type { BlogConfig } from '../src/index'
7
8
 
8
9
  type Props = {
9
10
  title: string
10
11
  canonicalUrl?: string
12
+ blogConfig?: BlogConfig
13
+ collectionName?: string
11
14
  }
12
15
 
16
+ const blogConfig = Astro.props.blogConfig ?? blogConfigDefault
17
+ const collectionName =
18
+ Astro.props.collectionName ?? blogConfigDefault.collectionName
19
+
13
20
  const locale = Astro.currentLocale
14
21
  const { title, canonicalUrl } = Astro.props
15
22
  const { blogSidebarCount, blogSidebarTitle, routeBasePath } = blogConfig
16
23
 
17
24
  // Get and filter posts by locale
18
- const allPosts = await getCollection('blog')
25
+ const allPosts = await getCollection(collectionName as CollectionKey)
19
26
  const filteredPosts = i18n
20
27
  ? allPosts.filter(({ id }) => {
21
28
  const [postLocale] = id.split('/')
@@ -0,0 +1,22 @@
1
+ ---
2
+ import { i18n } from 'astro:config/server'
3
+ import registry from 'virtual:shipyard-blog/registry'
4
+ import type { GetStaticPaths } from 'astro'
5
+ import { getInstanceConfig, getLocalePaths } from '../../src/staticPaths'
6
+ import BlogArchive from '../BlogArchive.astro'
7
+
8
+ export const getStaticPaths = (({ routePattern }) => {
9
+ const instance = getInstanceConfig(routePattern, registry)
10
+ return getLocalePaths(i18n).map((p) => ({
11
+ ...p,
12
+ props: instance,
13
+ }))
14
+ }) satisfies GetStaticPaths
15
+
16
+ const instance = getInstanceConfig(Astro.routePattern, registry)
17
+ const blogConfig = Astro.props.blogConfig ?? instance.blogConfig
18
+ const tagsMap = Astro.props.tagsMap ?? instance.tagsMap
19
+ const collectionName = Astro.props.collectionName ?? instance.collectionName
20
+ ---
21
+
22
+ <BlogArchive blogConfig={blogConfig} tagsMap={tagsMap} collectionName={collectionName} />
@@ -0,0 +1,30 @@
1
+ ---
2
+ import { i18n } from 'astro:config/server'
3
+ import { type CollectionKey, getCollection } from 'astro:content'
4
+ import registry from 'virtual:shipyard-blog/registry'
5
+ import type { GetStaticPaths } from 'astro'
6
+ import {
7
+ computeBlogAuthorPaths,
8
+ getInstanceConfig,
9
+ } from '../../src/staticPaths'
10
+ import BlogAuthorPage from '../BlogAuthorPage.astro'
11
+
12
+ export const getStaticPaths = (async ({ routePattern }) => {
13
+ const instance = getInstanceConfig(routePattern, registry)
14
+ const allPosts = await getCollection(instance.collectionName as CollectionKey)
15
+ return computeBlogAuthorPaths(allPosts, instance.blogConfig, i18n).map(
16
+ (p) => ({
17
+ ...p,
18
+ props: { ...p.props, ...instance },
19
+ }),
20
+ )
21
+ }) satisfies GetStaticPaths
22
+
23
+ const instance = getInstanceConfig(Astro.routePattern, registry)
24
+ const author = Astro.props.author
25
+ const blogConfig = Astro.props.blogConfig ?? instance.blogConfig
26
+ const tagsMap = Astro.props.tagsMap ?? instance.tagsMap
27
+ const collectionName = Astro.props.collectionName ?? instance.collectionName
28
+ ---
29
+
30
+ <BlogAuthorPage author={author} blogConfig={blogConfig} tagsMap={tagsMap} collectionName={collectionName} />
@@ -0,0 +1,23 @@
1
+ ---
2
+ import { i18n } from 'astro:config/server'
3
+ import registry from 'virtual:shipyard-blog/registry'
4
+ import type { GetStaticPaths } from 'astro'
5
+ import { getInstanceConfig, getLocalePaths } from '../../src/staticPaths'
6
+ import BlogAuthorsIndex from '../BlogAuthorsIndex.astro'
7
+
8
+ export const getStaticPaths = (({ routePattern }) => {
9
+ const instance = getInstanceConfig(routePattern, registry)
10
+ if (!instance.blogConfig.authorsEnabled) return []
11
+ return getLocalePaths(i18n).map((p) => ({
12
+ ...p,
13
+ props: instance,
14
+ }))
15
+ }) satisfies GetStaticPaths
16
+
17
+ const instance = getInstanceConfig(Astro.routePattern, registry)
18
+ const blogConfig = Astro.props.blogConfig ?? instance.blogConfig
19
+ const tagsMap = Astro.props.tagsMap ?? instance.tagsMap
20
+ const collectionName = Astro.props.collectionName ?? instance.collectionName
21
+ ---
22
+
23
+ <BlogAuthorsIndex blogConfig={blogConfig} tagsMap={tagsMap} collectionName={collectionName} />
@@ -0,0 +1,36 @@
1
+ ---
2
+ import { i18n } from 'astro:config/server'
3
+ import { type CollectionKey, getCollection } from 'astro:content'
4
+ import registry from 'virtual:shipyard-blog/registry'
5
+ import type { GetStaticPaths } from 'astro'
6
+ import { computeBlogEntryPaths, getInstanceConfig } from '../../src/staticPaths'
7
+ import BlogEntry from '../BlogEntry.astro'
8
+
9
+ export const getStaticPaths = (async ({ routePattern }) => {
10
+ const instance = getInstanceConfig(routePattern, registry)
11
+ const allPosts = await getCollection(instance.collectionName as CollectionKey)
12
+ return computeBlogEntryPaths(allPosts, instance.blogConfig, i18n).map(
13
+ (p) => ({
14
+ ...p,
15
+ props: { ...p.props, ...instance },
16
+ }),
17
+ )
18
+ }) satisfies GetStaticPaths
19
+
20
+ const instance = getInstanceConfig(Astro.routePattern, registry)
21
+ const entry = Astro.props.entry
22
+ const older = Astro.props.older
23
+ const newer = Astro.props.newer
24
+ const blogConfig = Astro.props.blogConfig ?? instance.blogConfig
25
+ const tagsMap = Astro.props.tagsMap ?? instance.tagsMap
26
+ const collectionName = Astro.props.collectionName ?? instance.collectionName
27
+ ---
28
+
29
+ <BlogEntry
30
+ entry={entry}
31
+ older={older}
32
+ newer={newer}
33
+ collectionName={collectionName}
34
+ blogConfig={blogConfig}
35
+ tagsMap={tagsMap}
36
+ />
@@ -0,0 +1,22 @@
1
+ ---
2
+ import { i18n } from 'astro:config/server'
3
+ import registry from 'virtual:shipyard-blog/registry'
4
+ import type { GetStaticPaths } from 'astro'
5
+ import { getInstanceConfig, getLocalePaths } from '../../src/staticPaths'
6
+ import BlogIndex from '../BlogIndex.astro'
7
+
8
+ export const getStaticPaths = (({ routePattern }) => {
9
+ const instance = getInstanceConfig(routePattern, registry)
10
+ return getLocalePaths(i18n).map((p) => ({
11
+ ...p,
12
+ props: instance,
13
+ }))
14
+ }) satisfies GetStaticPaths
15
+
16
+ const instance = getInstanceConfig(Astro.routePattern, registry)
17
+ const blogConfig = Astro.props.blogConfig ?? instance.blogConfig
18
+ const tagsMap = Astro.props.tagsMap ?? instance.tagsMap
19
+ const collectionName = Astro.props.collectionName ?? instance.collectionName
20
+ ---
21
+
22
+ <BlogIndex blogConfig={blogConfig} tagsMap={tagsMap} collectionName={collectionName} />
@@ -0,0 +1,29 @@
1
+ ---
2
+ import { i18n } from 'astro:config/server'
3
+ import { type CollectionKey, getCollection } from 'astro:content'
4
+ import registry from 'virtual:shipyard-blog/registry'
5
+ import type { GetStaticPaths } from 'astro'
6
+ import {
7
+ computeBlogPaginatedPaths,
8
+ getInstanceConfig,
9
+ } from '../../src/staticPaths'
10
+ import BlogIndexPaginated from '../BlogIndexPaginated.astro'
11
+
12
+ export const getStaticPaths = (async ({ routePattern }) => {
13
+ const instance = getInstanceConfig(routePattern, registry)
14
+ const allPosts = await getCollection(instance.collectionName as CollectionKey)
15
+ return computeBlogPaginatedPaths(allPosts, instance.blogConfig, i18n).map(
16
+ (p) => ({
17
+ ...p,
18
+ props: instance,
19
+ }),
20
+ )
21
+ }) satisfies GetStaticPaths
22
+
23
+ const instance = getInstanceConfig(Astro.routePattern, registry)
24
+ const blogConfig = Astro.props.blogConfig ?? instance.blogConfig
25
+ const tagsMap = Astro.props.tagsMap ?? instance.tagsMap
26
+ const collectionName = Astro.props.collectionName ?? instance.collectionName
27
+ ---
28
+
29
+ <BlogIndexPaginated blogConfig={blogConfig} tagsMap={tagsMap} collectionName={collectionName} />
@@ -0,0 +1,24 @@
1
+ ---
2
+ import { i18n } from 'astro:config/server'
3
+ import { type CollectionKey, getCollection } from 'astro:content'
4
+ import registry from 'virtual:shipyard-blog/registry'
5
+ import type { GetStaticPaths } from 'astro'
6
+ import { computeBlogTagPaths, getInstanceConfig } from '../../src/staticPaths'
7
+ import BlogTagPage from '../BlogTagPage.astro'
8
+
9
+ export const getStaticPaths = (async ({ routePattern }) => {
10
+ const instance = getInstanceConfig(routePattern, registry)
11
+ const allPosts = await getCollection(instance.collectionName as CollectionKey)
12
+ return computeBlogTagPaths(allPosts, instance.blogConfig, i18n).map((p) => ({
13
+ ...p,
14
+ props: instance,
15
+ }))
16
+ }) satisfies GetStaticPaths
17
+
18
+ const instance = getInstanceConfig(Astro.routePattern, registry)
19
+ const blogConfig = Astro.props.blogConfig ?? instance.blogConfig
20
+ const tagsMap = Astro.props.tagsMap ?? instance.tagsMap
21
+ const collectionName = Astro.props.collectionName ?? instance.collectionName
22
+ ---
23
+
24
+ <BlogTagPage blogConfig={blogConfig} tagsMap={tagsMap} collectionName={collectionName} />
@@ -0,0 +1,22 @@
1
+ ---
2
+ import { i18n } from 'astro:config/server'
3
+ import registry from 'virtual:shipyard-blog/registry'
4
+ import type { GetStaticPaths } from 'astro'
5
+ import { getInstanceConfig, getLocalePaths } from '../../src/staticPaths'
6
+ import BlogTagsIndex from '../BlogTagsIndex.astro'
7
+
8
+ export const getStaticPaths = (({ routePattern }) => {
9
+ const instance = getInstanceConfig(routePattern, registry)
10
+ return getLocalePaths(i18n).map((p) => ({
11
+ ...p,
12
+ props: instance,
13
+ }))
14
+ }) satisfies GetStaticPaths
15
+
16
+ const instance = getInstanceConfig(Astro.routePattern, registry)
17
+ const blogConfig = Astro.props.blogConfig ?? instance.blogConfig
18
+ const tagsMap = Astro.props.tagsMap ?? instance.tagsMap
19
+ const collectionName = Astro.props.collectionName ?? instance.collectionName
20
+ ---
21
+
22
+ <BlogTagsIndex blogConfig={blogConfig} tagsMap={tagsMap} collectionName={collectionName} />
@@ -0,0 +1,28 @@
1
+ import { i18n } from 'astro:config/server'
2
+ import { type CollectionKey, getCollection } from 'astro:content'
3
+ import registry from 'virtual:shipyard-blog/registry'
4
+ import type { APIContext, GetStaticPaths } from 'astro'
5
+ import { createAtomResponse } from '../../../src/feeds'
6
+ import { getInstanceConfig, getLocalePaths } from '../../../src/staticPaths'
7
+
8
+ export const getStaticPaths = (({ routePattern }) => {
9
+ const { blogConfig } = getInstanceConfig(routePattern, registry)
10
+ if (!blogConfig.feedOptions?.atom) return []
11
+ return getLocalePaths(i18n)
12
+ }) satisfies GetStaticPaths
13
+
14
+ export const GET = async (context: APIContext) => {
15
+ const { blogConfig, collectionName } = getInstanceConfig(
16
+ context.routePattern,
17
+ registry,
18
+ )
19
+ const allPosts = await getCollection(collectionName as CollectionKey)
20
+ return createAtomResponse({
21
+ allPosts,
22
+ blogConfig,
23
+ site: context.site,
24
+ currentLocale: context.currentLocale,
25
+ i18n,
26
+ isDev: import.meta.env.DEV,
27
+ })
28
+ }
@@ -0,0 +1,28 @@
1
+ import { i18n } from 'astro:config/server'
2
+ import { type CollectionKey, getCollection } from 'astro:content'
3
+ import registry from 'virtual:shipyard-blog/registry'
4
+ import type { APIContext, GetStaticPaths } from 'astro'
5
+ import { createJsonFeedResponse } from '../../../src/feeds'
6
+ import { getInstanceConfig, getLocalePaths } from '../../../src/staticPaths'
7
+
8
+ export const getStaticPaths = (({ routePattern }) => {
9
+ const { blogConfig } = getInstanceConfig(routePattern, registry)
10
+ if (!blogConfig.feedOptions?.json) return []
11
+ return getLocalePaths(i18n)
12
+ }) satisfies GetStaticPaths
13
+
14
+ export const GET = async (context: APIContext) => {
15
+ const { blogConfig, collectionName } = getInstanceConfig(
16
+ context.routePattern,
17
+ registry,
18
+ )
19
+ const allPosts = await getCollection(collectionName as CollectionKey)
20
+ return createJsonFeedResponse({
21
+ allPosts,
22
+ blogConfig,
23
+ site: context.site,
24
+ currentLocale: context.currentLocale,
25
+ i18n,
26
+ isDev: import.meta.env.DEV,
27
+ })
28
+ }
@@ -0,0 +1,28 @@
1
+ import { i18n } from 'astro:config/server'
2
+ import { type CollectionKey, getCollection } from 'astro:content'
3
+ import registry from 'virtual:shipyard-blog/registry'
4
+ import type { APIContext, GetStaticPaths } from 'astro'
5
+ import { createRssResponse } from '../../../src/feeds'
6
+ import { getInstanceConfig, getLocalePaths } from '../../../src/staticPaths'
7
+
8
+ export const getStaticPaths = (({ routePattern }) => {
9
+ const { blogConfig } = getInstanceConfig(routePattern, registry)
10
+ if (!blogConfig.feedOptions?.rss) return []
11
+ return getLocalePaths(i18n)
12
+ }) satisfies GetStaticPaths
13
+
14
+ export const GET = async (context: APIContext) => {
15
+ const { blogConfig, collectionName } = getInstanceConfig(
16
+ context.routePattern,
17
+ registry,
18
+ )
19
+ const allPosts = await getCollection(collectionName as CollectionKey)
20
+ return createRssResponse({
21
+ allPosts,
22
+ blogConfig,
23
+ site: context.site,
24
+ currentLocale: context.currentLocale,
25
+ i18n,
26
+ isDev: import.meta.env.DEV,
27
+ })
28
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levino/shipyard-blog",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "Blog plugin for shipyard with pagination, sidebar, and git metadata",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -12,7 +12,9 @@
12
12
  },
13
13
  "./index.css": "./index.css",
14
14
  "./astro": "./src/astro.ts",
15
- "./astro/*": "./astro/*"
15
+ "./astro/*": "./astro/*",
16
+ "./staticPaths": "./src/staticPaths.ts",
17
+ "./feeds": "./src/feeds.ts"
16
18
  },
17
19
  "files": [
18
20
  "astro",
@@ -31,7 +33,7 @@
31
33
  "license": "MIT",
32
34
  "homepage": "https://shipyard.levinkeller.de",
33
35
  "dependencies": {
34
- "@levino/shipyard-base": "^0.7.4",
36
+ "@levino/shipyard-base": "^0.7.5",
35
37
  "ramda": "^0.31",
36
38
  "yaml": "^2.0.0"
37
39
  },