@levino/shipyard-blog 0.7.2 → 0.7.3

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,4 +1,5 @@
1
1
  ---
2
+ import { Image } from 'astro:assets'
2
3
  import { i18n } from 'astro:config/server'
3
4
  import { type CollectionEntry, getCollection } from 'astro:content'
4
5
  import blogConfig from 'virtual:shipyard-blog/config'
@@ -152,7 +153,7 @@ const tagBaseUrl = i18n
152
153
  <article class="card bg-base-100 shadow-sm" data-testid="blog-post-item">
153
154
  <figure>
154
155
  <a href={postLink} data-testid="blog-post-link">
155
- <img
156
+ <Image
156
157
  src={entry.data.image}
157
158
  alt={entry.data.title}
158
159
  class="w-full object-cover"
@@ -189,7 +190,7 @@ const tagBaseUrl = i18n
189
190
  <article class="card card-side bg-base-100 shadow-sm" data-testid="blog-post-item">
190
191
  <figure class="hidden w-48 flex-shrink-0 sm:block">
191
192
  <a href={postLink}>
192
- <img
193
+ <Image
193
194
  src={entry.data.image}
194
195
  alt={entry.data.title}
195
196
  class="h-full w-full object-cover"
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import { Image } from 'astro:assets'
2
3
  import { i18n } from 'astro:config/server'
3
4
  import { getCollection } from 'astro:content'
4
5
  import blogConfig from 'virtual:shipyard-blog/config'
@@ -125,7 +126,7 @@ const showRightEllipsis =
125
126
  {hasImage && (
126
127
  <figure class="hidden w-48 flex-shrink-0 sm:block">
127
128
  <a href={postLink}>
128
- <img
129
+ <Image
129
130
  src={entry.data.image}
130
131
  alt={entry.data.title}
131
132
  class="h-full w-full object-cover"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levino/shipyard-blog",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Blog plugin for shipyard with pagination, sidebar, and git metadata",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -31,7 +31,7 @@
31
31
  "license": "MIT",
32
32
  "homepage": "https://shipyard.levinkeller.de",
33
33
  "dependencies": {
34
- "@levino/shipyard-base": "^0.7.2",
34
+ "@levino/shipyard-base": "^0.7.3",
35
35
  "ramda": "^0.31",
36
36
  "yaml": "^2.0.0"
37
37
  },
package/src/index.ts CHANGED
@@ -67,99 +67,100 @@ export const tagSchema = z.object({
67
67
 
68
68
  export type Tag = z.infer<typeof tagSchema>
69
69
 
70
- export const blogSchema = z.object({
71
- date: z.date(),
72
- title: z.string(),
73
- /**
74
- * SEO title override for the page's <title> and meta tags.
75
- * If not provided, uses the title field.
76
- */
77
- title_meta: z.string().optional(),
78
- description: z.string(),
79
- /**
80
- * Post author(s). Can be:
81
- * - A string referencing an author from authors.yml
82
- * - An inline author object
83
- * - An array of author references or objects
84
- */
85
- authors: z
86
- .union([
87
- z.string(),
88
- authorSchema,
89
- z.array(z.union([z.string(), authorSchema])),
90
- ])
91
- .optional(),
92
- /**
93
- * Post tags for categorization.
94
- */
95
- tags: z.array(z.string()).optional(),
96
- /**
97
- * Social card/preview image for the post.
98
- */
99
- image: z.string().optional(),
100
- /**
101
- * SEO keywords for the post.
102
- */
103
- keywords: z.array(z.string()).optional(),
104
- /**
105
- * Custom URL slug for the post.
106
- */
107
- slug: z.string().optional(),
108
- /**
109
- * Mark post as draft (excluded from production builds).
110
- */
111
- draft: z.boolean().default(false),
112
- /**
113
- * Mark post as unlisted (accessible but hidden from listings).
114
- */
115
- unlisted: z.boolean().default(false),
116
- /**
117
- * Hide the table of contents for this post.
118
- */
119
- hide_table_of_contents: z.boolean().default(false),
120
- /**
121
- * Sidebar configuration for this blog post.
122
- */
123
- sidebar: z
124
- .object({
125
- /**
126
- * Custom label for this post in the blog sidebar.
127
- * If not provided, uses the title.
128
- */
129
- label: z.string().optional(),
130
- })
131
- .default({}),
132
- /**
133
- * Minimum heading level to include in table of contents.
134
- * @default 2
135
- */
136
- toc_min_heading_level: z.number().int().min(1).max(6).default(2),
137
- /**
138
- * Maximum heading level to include in table of contents.
139
- * @default 3
140
- */
141
- toc_max_heading_level: z.number().int().min(1).max(6).default(3),
142
- /**
143
- * Override the last update author for this specific post.
144
- * Set to false to hide the author for this post.
145
- */
146
- last_update_author: z.union([z.string(), z.literal(false)]).optional(),
147
- /**
148
- * Override the last update timestamp for this specific post.
149
- * Set to false to hide the timestamp for this post.
150
- */
151
- last_update_time: z.union([z.coerce.date(), z.literal(false)]).optional(),
152
- /**
153
- * Custom edit URL for this specific post.
154
- * Set to null to disable edit link for this post.
155
- */
156
- custom_edit_url: z.string().nullable().optional(),
157
- /**
158
- * Custom canonical URL for this post.
159
- * Useful when content is duplicated or when migrating URLs.
160
- */
161
- canonical_url: z.string().optional(),
162
- })
70
+ export const blogSchema = ({ image }: { image: () => z.ZodType }) =>
71
+ z.object({
72
+ date: z.date(),
73
+ title: z.string(),
74
+ /**
75
+ * SEO title override for the page's <title> and meta tags.
76
+ * If not provided, uses the title field.
77
+ */
78
+ title_meta: z.string().optional(),
79
+ description: z.string(),
80
+ /**
81
+ * Post author(s). Can be:
82
+ * - A string referencing an author from authors.yml
83
+ * - An inline author object
84
+ * - An array of author references or objects
85
+ */
86
+ authors: z
87
+ .union([
88
+ z.string(),
89
+ authorSchema,
90
+ z.array(z.union([z.string(), authorSchema])),
91
+ ])
92
+ .optional(),
93
+ /**
94
+ * Post tags for categorization.
95
+ */
96
+ tags: z.array(z.string()).optional(),
97
+ /**
98
+ * Image for the post. Use a relative path to a local image file.
99
+ */
100
+ image: image().optional(),
101
+ /**
102
+ * SEO keywords for the post.
103
+ */
104
+ keywords: z.array(z.string()).optional(),
105
+ /**
106
+ * Custom URL slug for the post.
107
+ */
108
+ slug: z.string().optional(),
109
+ /**
110
+ * Mark post as draft (excluded from production builds).
111
+ */
112
+ draft: z.boolean().default(false),
113
+ /**
114
+ * Mark post as unlisted (accessible but hidden from listings).
115
+ */
116
+ unlisted: z.boolean().default(false),
117
+ /**
118
+ * Hide the table of contents for this post.
119
+ */
120
+ hide_table_of_contents: z.boolean().default(false),
121
+ /**
122
+ * Sidebar configuration for this blog post.
123
+ */
124
+ sidebar: z
125
+ .object({
126
+ /**
127
+ * Custom label for this post in the blog sidebar.
128
+ * If not provided, uses the title.
129
+ */
130
+ label: z.string().optional(),
131
+ })
132
+ .default({}),
133
+ /**
134
+ * Minimum heading level to include in table of contents.
135
+ * @default 2
136
+ */
137
+ toc_min_heading_level: z.number().int().min(1).max(6).default(2),
138
+ /**
139
+ * Maximum heading level to include in table of contents.
140
+ * @default 3
141
+ */
142
+ toc_max_heading_level: z.number().int().min(1).max(6).default(3),
143
+ /**
144
+ * Override the last update author for this specific post.
145
+ * Set to false to hide the author for this post.
146
+ */
147
+ last_update_author: z.union([z.string(), z.literal(false)]).optional(),
148
+ /**
149
+ * Override the last update timestamp for this specific post.
150
+ * Set to false to hide the timestamp for this post.
151
+ */
152
+ last_update_time: z.union([z.coerce.date(), z.literal(false)]).optional(),
153
+ /**
154
+ * Custom edit URL for this specific post.
155
+ * Set to null to disable edit link for this post.
156
+ */
157
+ custom_edit_url: z.string().nullable().optional(),
158
+ /**
159
+ * Custom canonical URL for this post.
160
+ * Useful when content is duplicated or when migrating URLs.
161
+ */
162
+ canonical_url: z.string().optional(),
163
+ })
163
164
 
164
165
  export const blogConfigSchema = z.object({
165
166
  /**