chaingrow-blog 0.2.2 → 0.7.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.
@@ -0,0 +1,636 @@
1
+ import {
2
+ SCHEMA_ORG_CONTEXT,
3
+ buildBlogJsonLd,
4
+ createClient,
5
+ interleaveMedia
6
+ } from "./chunk-K3HNYPEP.js";
7
+
8
+ // src/next/metadata.ts
9
+ var trimTrailingSlash = (s) => s.replace(/\/+$/, "");
10
+ var normalizePathPrefix = (s) => {
11
+ let p = s.trim();
12
+ if (!p.startsWith("/")) p = "/" + p;
13
+ while (p.length > 1 && p.endsWith("/")) p = p.slice(0, -1);
14
+ return p;
15
+ };
16
+ var blogUrlFor = (alternates, language, slug) => {
17
+ const base = trimTrailingSlash(alternates.siteUrl);
18
+ const rawPrefix = typeof alternates.pathPrefix === "function" ? alternates.pathPrefix(language) : alternates.pathPrefix ?? "/blog";
19
+ return `${base}${normalizePathPrefix(rawPrefix)}/${slug}`;
20
+ };
21
+ async function generateBlogMetadata(slug, language, opts) {
22
+ const blog = await getBlog(slug, language, opts);
23
+ if (!blog) return {};
24
+ const images = blog.og_image ? [blog.og_image] : void 0;
25
+ const description = blog.description ?? void 0;
26
+ const meta = {
27
+ title: blog.title,
28
+ ...description ? { description } : {},
29
+ openGraph: {
30
+ type: "article",
31
+ title: blog.title,
32
+ ...description ? { description } : {},
33
+ ...images ? { images } : {},
34
+ ...blog.published_at ? { publishedTime: blog.published_at } : {}
35
+ },
36
+ twitter: {
37
+ card: blog.og_image ? "summary_large_image" : "summary",
38
+ title: blog.title,
39
+ ...description ? { description } : {},
40
+ ...images ? { images } : {}
41
+ }
42
+ };
43
+ if (opts?.alternates) {
44
+ const alternates = opts.alternates;
45
+ const canonical = blogUrlFor(alternates, blog.language, blog.slug);
46
+ let languages;
47
+ try {
48
+ const all = await listBlogs({ status: "PUBLISHED" }, opts);
49
+ const variants = all.filter((b) => b.slug === blog.slug && b.language);
50
+ if (variants.length > 1) {
51
+ languages = {};
52
+ for (const variant of variants) {
53
+ languages[variant.language] = blogUrlFor(
54
+ alternates,
55
+ variant.language,
56
+ variant.slug
57
+ );
58
+ }
59
+ const xDefaultUrl = alternates.xDefaultLanguage ? languages[alternates.xDefaultLanguage] : void 0;
60
+ if (xDefaultUrl) languages["x-default"] = xDefaultUrl;
61
+ }
62
+ } catch (err) {
63
+ console.error(
64
+ "chaingrow-blog: hreflang variant lookup failed, emitting canonical only:",
65
+ err
66
+ );
67
+ }
68
+ meta.alternates = {
69
+ canonical,
70
+ ...languages ? { languages } : {}
71
+ };
72
+ }
73
+ return meta;
74
+ }
75
+ function generateBlogIndexMetadata(opts) {
76
+ const { title, description, canonical, ogImage } = opts;
77
+ const images = ogImage ? [ogImage] : void 0;
78
+ return {
79
+ title,
80
+ ...description ? { description } : {},
81
+ ...canonical ? { alternates: { canonical } } : {},
82
+ openGraph: {
83
+ type: "website",
84
+ title,
85
+ ...description ? { description } : {},
86
+ ...canonical ? { url: canonical } : {},
87
+ ...images ? { images } : {}
88
+ },
89
+ twitter: {
90
+ card: ogImage ? "summary_large_image" : "summary",
91
+ title,
92
+ ...description ? { description } : {},
93
+ ...images ? { images } : {}
94
+ }
95
+ };
96
+ }
97
+
98
+ // src/next/BlogPage.tsx
99
+ import { notFound } from "next/navigation";
100
+
101
+ // src/react/defaults.tsx
102
+ import { jsx, jsxs } from "react/jsx-runtime";
103
+ var DefaultHeading = ({
104
+ level,
105
+ children,
106
+ className
107
+ }) => {
108
+ if (level === 1) return /* @__PURE__ */ jsx("h1", { className, children });
109
+ if (level === 3) return /* @__PURE__ */ jsx("h3", { className, children });
110
+ return /* @__PURE__ */ jsx("h2", { className, children });
111
+ };
112
+ var DefaultParagraph = ({
113
+ children,
114
+ className
115
+ }) => /* @__PURE__ */ jsx("p", { className, children });
116
+ var DefaultBulletList = ({
117
+ items,
118
+ className,
119
+ renderBlock
120
+ }) => /* @__PURE__ */ jsx("ul", { className, children: items.map((item, i) => /* @__PURE__ */ jsx("li", { children: item.content.map((b, j) => renderBlock(b, j)) }, i)) });
121
+ var DefaultOrderedList = ({
122
+ items,
123
+ className,
124
+ renderBlock
125
+ }) => /* @__PURE__ */ jsx("ol", { className, children: items.map((item, i) => /* @__PURE__ */ jsx("li", { children: item.content.map((b, j) => renderBlock(b, j)) }, i)) });
126
+ var DefaultBlockquote = ({
127
+ children,
128
+ className
129
+ }) => /* @__PURE__ */ jsx("blockquote", { className, children });
130
+ var DefaultCodeBlock = ({
131
+ language,
132
+ code,
133
+ className
134
+ }) => /* @__PURE__ */ jsx("pre", { className, children: /* @__PURE__ */ jsx("code", { className: language ? `language-${language}` : void 0, children: code }) });
135
+ var DefaultImage = ({
136
+ src,
137
+ alt,
138
+ caption,
139
+ width,
140
+ height,
141
+ className
142
+ }) => {
143
+ const img = (
144
+ // eslint-disable-next-line @next/next/no-img-element
145
+ /* @__PURE__ */ jsx("img", { src, alt, width, height })
146
+ );
147
+ if (caption) {
148
+ return /* @__PURE__ */ jsxs("figure", { className, children: [
149
+ img,
150
+ /* @__PURE__ */ jsx("figcaption", { children: caption })
151
+ ] });
152
+ }
153
+ return /* @__PURE__ */ jsx("span", { className, children: img });
154
+ };
155
+ var DefaultDivider = ({ className }) => /* @__PURE__ */ jsx("hr", { className });
156
+ var DefaultMedia = ({ media }) => {
157
+ if (media.media_type === "VIDEO") {
158
+ return /* @__PURE__ */ jsx(
159
+ "video",
160
+ {
161
+ src: media.media_url,
162
+ controls: true,
163
+ playsInline: true,
164
+ preload: "metadata"
165
+ }
166
+ );
167
+ }
168
+ return /* @__PURE__ */ jsx("img", { src: media.media_url, alt: media.prompt });
169
+ };
170
+
171
+ // src/react/BlogRenderer.tsx
172
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
173
+ var MARK_ORDER = [
174
+ "bold",
175
+ "italic",
176
+ "strike",
177
+ "code",
178
+ "link"
179
+ ];
180
+ function InlineRenderer({ inline }) {
181
+ return /* @__PURE__ */ jsx2(Fragment, { children: inline.map((run, i) => /* @__PURE__ */ jsx2(InlineRun, { run }, i)) });
182
+ }
183
+ function InlineRun({ run }) {
184
+ const marks = run.marks ? [...run.marks].sort(
185
+ (a, b) => MARK_ORDER.indexOf(b.type) - MARK_ORDER.indexOf(a.type)
186
+ ) : [];
187
+ let node = run.text;
188
+ for (const mark of marks) {
189
+ switch (mark.type) {
190
+ case "bold":
191
+ node = /* @__PURE__ */ jsx2("strong", { children: node });
192
+ break;
193
+ case "italic":
194
+ node = /* @__PURE__ */ jsx2("em", { children: node });
195
+ break;
196
+ case "strike":
197
+ node = /* @__PURE__ */ jsx2("s", { children: node });
198
+ break;
199
+ case "code":
200
+ node = /* @__PURE__ */ jsx2("code", { children: node });
201
+ break;
202
+ case "link":
203
+ node = /* @__PURE__ */ jsx2("a", { href: mark.href, rel: "noopener noreferrer", children: node });
204
+ break;
205
+ }
206
+ }
207
+ return /* @__PURE__ */ jsx2(Fragment, { children: node });
208
+ }
209
+ function BlockRenderer({
210
+ block,
211
+ components = {},
212
+ classNames = {},
213
+ renderBlock
214
+ }) {
215
+ const recurse = renderBlock ?? ((b, i) => /* @__PURE__ */ jsx2(
216
+ BlockRenderer,
217
+ {
218
+ block: b,
219
+ components,
220
+ classNames,
221
+ renderBlock: recurse
222
+ },
223
+ i
224
+ ));
225
+ switch (block.type) {
226
+ case "heading": {
227
+ const Heading = components.heading ?? DefaultHeading;
228
+ return /* @__PURE__ */ jsx2(Heading, { level: block.level, className: classNames.heading, children: /* @__PURE__ */ jsx2(InlineRenderer, { inline: block.content }) });
229
+ }
230
+ case "paragraph": {
231
+ const Paragraph = components.paragraph ?? DefaultParagraph;
232
+ return /* @__PURE__ */ jsx2(Paragraph, { className: classNames.paragraph, children: /* @__PURE__ */ jsx2(InlineRenderer, { inline: block.content }) });
233
+ }
234
+ case "bulletList": {
235
+ const BulletList = components.bulletList ?? DefaultBulletList;
236
+ return /* @__PURE__ */ jsx2(
237
+ BulletList,
238
+ {
239
+ items: block.items,
240
+ className: classNames.bulletList,
241
+ renderBlock: recurse
242
+ }
243
+ );
244
+ }
245
+ case "orderedList": {
246
+ const OrderedList = components.orderedList ?? DefaultOrderedList;
247
+ return /* @__PURE__ */ jsx2(
248
+ OrderedList,
249
+ {
250
+ items: block.items,
251
+ className: classNames.orderedList,
252
+ renderBlock: recurse
253
+ }
254
+ );
255
+ }
256
+ case "blockquote": {
257
+ const Blockquote = components.blockquote ?? DefaultBlockquote;
258
+ return /* @__PURE__ */ jsx2(Blockquote, { className: classNames.blockquote, children: /* @__PURE__ */ jsx2(InlineRenderer, { inline: block.content }) });
259
+ }
260
+ case "codeBlock": {
261
+ const CodeBlock = components.codeBlock ?? DefaultCodeBlock;
262
+ return /* @__PURE__ */ jsx2(
263
+ CodeBlock,
264
+ {
265
+ language: block.language,
266
+ code: block.code,
267
+ className: classNames.codeBlock
268
+ }
269
+ );
270
+ }
271
+ case "image": {
272
+ const ImageComp = components.image ?? DefaultImage;
273
+ return /* @__PURE__ */ jsx2(
274
+ ImageComp,
275
+ {
276
+ src: block.src,
277
+ alt: block.alt,
278
+ caption: block.caption,
279
+ width: block.width,
280
+ height: block.height,
281
+ mediaId: block.mediaId,
282
+ className: classNames.image
283
+ }
284
+ );
285
+ }
286
+ case "divider": {
287
+ const Divider = components.divider ?? DefaultDivider;
288
+ return /* @__PURE__ */ jsx2(Divider, { className: classNames.divider });
289
+ }
290
+ }
291
+ }
292
+ function BlogRenderer({
293
+ blog,
294
+ components = {},
295
+ classNames = {}
296
+ }) {
297
+ const Media = components.media ?? DefaultMedia;
298
+ const Wrapper = components.wrapper;
299
+ const slots = interleaveMedia(blog.blocks, blog.generatedMedia);
300
+ const content = /* @__PURE__ */ jsx2(Fragment, { children: slots.map(
301
+ (slot) => slot.kind === "block" ? /* @__PURE__ */ jsx2(
302
+ BlockRenderer,
303
+ {
304
+ block: slot.block,
305
+ components,
306
+ classNames
307
+ },
308
+ `b:${slot.index}`
309
+ ) : /* @__PURE__ */ jsx2(Media, { media: slot.media }, `m:${slot.media.id}`)
310
+ ) });
311
+ if (Wrapper) return /* @__PURE__ */ jsx2(Wrapper, { blog, children: content });
312
+ return content;
313
+ }
314
+
315
+ // src/react/BlogDetail.tsx
316
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
317
+ var defaultFormatDate = (iso) => new Date(iso).toLocaleDateString();
318
+ function DefaultHeader({
319
+ blog,
320
+ formatDate
321
+ }) {
322
+ const hasInlineMedia = (blog.generatedMedia?.length ?? 0) > 0;
323
+ const heroImage = !hasInlineMedia && blog.og_image ? /* @__PURE__ */ jsx3("img", { src: blog.og_image, alt: blog.title }) : null;
324
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
325
+ heroImage,
326
+ /* @__PURE__ */ jsx3("h1", { children: blog.title }),
327
+ blog.published_at && /* @__PURE__ */ jsx3("time", { dateTime: blog.published_at, children: formatDate(blog.published_at) }),
328
+ blog.description && /* @__PURE__ */ jsx3("p", { children: blog.description })
329
+ ] });
330
+ }
331
+ function BlogDetail({
332
+ blog,
333
+ components,
334
+ formatDate = defaultFormatDate
335
+ }) {
336
+ const Header = components?.Header ?? DefaultHeader;
337
+ const Footer = components?.Footer;
338
+ return /* @__PURE__ */ jsxs2("article", { children: [
339
+ /* @__PURE__ */ jsx3(Header, { blog, formatDate }),
340
+ /* @__PURE__ */ jsx3(BlogRenderer, { blog, components: components?.blocks }),
341
+ Footer ? /* @__PURE__ */ jsx3(Footer, { blog }) : null
342
+ ] });
343
+ }
344
+
345
+ // src/react/BlogJsonLd.tsx
346
+ import { jsx as jsx4 } from "react/jsx-runtime";
347
+ function JsonLdGraph({
348
+ items
349
+ }) {
350
+ if (!items || items.length === 0) return null;
351
+ const payload = JSON.stringify({
352
+ "@context": SCHEMA_ORG_CONTEXT,
353
+ "@graph": items
354
+ });
355
+ return /* @__PURE__ */ jsx4(
356
+ "script",
357
+ {
358
+ type: "application/ld+json",
359
+ dangerouslySetInnerHTML: { __html: payload }
360
+ }
361
+ );
362
+ }
363
+ function BlogJsonLd({
364
+ blog,
365
+ extraSchemas,
366
+ ...opts
367
+ }) {
368
+ const items = [...extraSchemas ?? [], ...buildBlogJsonLd(blog, opts)];
369
+ return /* @__PURE__ */ jsx4(JsonLdGraph, { items });
370
+ }
371
+
372
+ // src/next/BlogPage.tsx
373
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
374
+ async function BlogPage({
375
+ params
376
+ }) {
377
+ const { slug, locale } = await params;
378
+ let blog = null;
379
+ try {
380
+ blog = await getBlog(slug, locale);
381
+ } catch (err) {
382
+ console.error("chaingrow-blog: <BlogPage> getBlog failed:", err);
383
+ }
384
+ if (!blog) notFound();
385
+ return /* @__PURE__ */ jsxs3("div", { className: "cg-blog-article", children: [
386
+ /* @__PURE__ */ jsx5("style", { dangerouslySetInnerHTML: { __html: ARTICLE_CSS } }),
387
+ /* @__PURE__ */ jsx5(BlogJsonLd, { blog }),
388
+ /* @__PURE__ */ jsx5(BlogDetail, { blog })
389
+ ] });
390
+ }
391
+ var ARTICLE_CSS = `
392
+ .cg-blog-article {
393
+ max-width: 720px;
394
+ margin: 0 auto;
395
+ padding: 4rem 1.5rem 6rem;
396
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
397
+ font-size: 1.0625rem;
398
+ line-height: 1.7;
399
+ color: inherit;
400
+ -webkit-font-smoothing: antialiased;
401
+ -moz-osx-font-smoothing: grayscale;
402
+ }
403
+ .cg-blog-article h1 {
404
+ font-size: clamp(2rem, 4vw, 2.625rem);
405
+ font-weight: 700;
406
+ line-height: 1.15;
407
+ letter-spacing: -0.022em;
408
+ color: inherit;
409
+ margin: 0 0 1rem;
410
+ }
411
+ .cg-blog-article time {
412
+ display: block;
413
+ font-size: 0.8125rem;
414
+ color: currentColor;
415
+ opacity: 0.55;
416
+ margin: 0 0 2rem;
417
+ font-weight: 400;
418
+ }
419
+ .cg-blog-article h2 {
420
+ font-size: 1.625rem;
421
+ font-weight: 700;
422
+ line-height: 1.25;
423
+ letter-spacing: -0.015em;
424
+ color: inherit;
425
+ margin: 3rem 0 1rem;
426
+ }
427
+ .cg-blog-article h3 {
428
+ font-size: 1.25rem;
429
+ font-weight: 700;
430
+ line-height: 1.3;
431
+ color: inherit;
432
+ margin: 2.25rem 0 0.75rem;
433
+ }
434
+ .cg-blog-article h4 {
435
+ font-size: 1.0625rem;
436
+ font-weight: 700;
437
+ color: inherit;
438
+ margin: 1.75rem 0 0.5rem;
439
+ }
440
+ .cg-blog-article p {
441
+ margin: 0 0 1.25rem;
442
+ color: inherit;
443
+ }
444
+ .cg-blog-article a {
445
+ color: inherit;
446
+ text-decoration: underline;
447
+ text-underline-offset: 3px;
448
+ text-decoration-thickness: 1px;
449
+ transition: opacity 150ms ease;
450
+ }
451
+ .cg-blog-article a:hover { opacity: 0.7; }
452
+ .cg-blog-article strong { color: inherit; font-weight: 700; }
453
+ .cg-blog-article em { font-style: italic; }
454
+ .cg-blog-article ul,
455
+ .cg-blog-article ol {
456
+ margin: 0 0 1.5rem;
457
+ padding-left: 1.5rem;
458
+ color: inherit;
459
+ }
460
+ .cg-blog-article li {
461
+ margin-bottom: 0.5rem;
462
+ line-height: 1.65;
463
+ }
464
+ .cg-blog-article li > p { margin: 0 0 0.5rem; }
465
+ .cg-blog-article li:last-child > p:last-child { margin-bottom: 0; }
466
+ .cg-blog-article blockquote {
467
+ margin: 2rem 0;
468
+ padding: 0.5rem 0 0.5rem 1.5rem;
469
+ border-left: 3px solid currentColor;
470
+ font-style: italic;
471
+ color: inherit;
472
+ font-size: 1.125rem;
473
+ line-height: 1.6;
474
+ }
475
+ .cg-blog-article blockquote p:last-child { margin-bottom: 0; }
476
+ .cg-blog-article img {
477
+ display: block;
478
+ width: 100%;
479
+ height: auto;
480
+ margin: 2.25rem 0;
481
+ border-radius: 6px;
482
+ background: rgba(128, 128, 128, 0.08);
483
+ }
484
+ .cg-blog-article video {
485
+ display: block;
486
+ width: 100%;
487
+ height: auto;
488
+ margin: 2.25rem 0;
489
+ border-radius: 6px;
490
+ background: rgba(128, 128, 128, 0.15);
491
+ }
492
+ .cg-blog-article hr {
493
+ border: 0;
494
+ height: 1px;
495
+ background: currentColor;
496
+ opacity: 0.15;
497
+ margin: 3rem 0;
498
+ }
499
+ .cg-blog-article code {
500
+ background: rgba(128, 128, 128, 0.15);
501
+ color: inherit;
502
+ padding: 0.15em 0.4em;
503
+ border-radius: 3px;
504
+ font-size: 0.9em;
505
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
506
+ }
507
+ .cg-blog-article pre {
508
+ background: rgba(128, 128, 128, 0.12);
509
+ color: inherit;
510
+ padding: 1.25rem 1.5rem;
511
+ border-radius: 6px;
512
+ overflow-x: auto;
513
+ font-size: 0.9375rem;
514
+ line-height: 1.6;
515
+ margin: 1.75rem 0;
516
+ }
517
+ .cg-blog-article pre code {
518
+ background: transparent;
519
+ color: inherit;
520
+ padding: 0;
521
+ border-radius: 0;
522
+ font-size: inherit;
523
+ }
524
+ @media (max-width: 640px) {
525
+ .cg-blog-article {
526
+ padding: 2.5rem 1.25rem 4rem;
527
+ font-size: 1rem;
528
+ }
529
+ .cg-blog-article h2 { margin-top: 2.25rem; }
530
+ .cg-blog-article h3 { margin-top: 1.75rem; }
531
+ }
532
+ `;
533
+ function generateBlogPageMetadata(opts) {
534
+ return async ({ params }) => {
535
+ const { slug, locale } = await params;
536
+ try {
537
+ return await generateBlogMetadata(slug, locale, opts);
538
+ } catch (err) {
539
+ console.error(
540
+ "chaingrow-blog: generateBlogPageMetadata failed:",
541
+ err
542
+ );
543
+ return {};
544
+ }
545
+ };
546
+ }
547
+
548
+ // src/next/index.ts
549
+ var DEFAULT_API_URL = "https://api.chaingrow.de";
550
+ var DEFAULT_REVALIDATE_SECONDS = 60 * 60 * 24 * 7;
551
+ var resolveEnv = (opts = {}) => {
552
+ const apiUrl = opts.apiUrl ?? process.env.CHAINGROW_API_URL ?? DEFAULT_API_URL;
553
+ const apiKey = opts.apiKey ?? process.env.CHAINGROW_API_KEY;
554
+ if (!apiKey) {
555
+ throw new Error(
556
+ "chaingrow-blog: CHAINGROW_API_KEY is not set (env var or apiKey option required)"
557
+ );
558
+ }
559
+ return { apiUrl, apiKey };
560
+ };
561
+ var buildFetch = (tag, revalidate) => {
562
+ const effectiveRevalidate = revalidate === void 0 ? DEFAULT_REVALIDATE_SECONDS : revalidate;
563
+ return ((input, init) => fetch(input, {
564
+ ...init,
565
+ next: {
566
+ tags: ["chaingrow:blog", tag],
567
+ revalidate: effectiveRevalidate
568
+ }
569
+ }));
570
+ };
571
+ async function getBlog(slug, language, opts = {}) {
572
+ const { apiUrl, apiKey } = resolveEnv(opts);
573
+ const client = createClient({
574
+ apiUrl,
575
+ apiKey,
576
+ fetch: buildFetch(`chaingrow:blog:${slug}`, opts.revalidate)
577
+ });
578
+ return client.getBlog(slug, language);
579
+ }
580
+ async function listBlogs(listOpts = {}, opts = {}) {
581
+ const { apiUrl, apiKey } = resolveEnv(opts);
582
+ const client = createClient({
583
+ apiUrl,
584
+ apiKey,
585
+ fetch: buildFetch("chaingrow:blog:list", opts.revalidate)
586
+ });
587
+ return client.listBlogs(listOpts);
588
+ }
589
+ var trimTrailingSlash2 = (s) => s.replace(/\/+$/, "");
590
+ var normalizePathPrefix2 = (s) => {
591
+ let p = s.trim();
592
+ if (!p.startsWith("/")) p = "/" + p;
593
+ while (p.length > 1 && p.endsWith("/")) p = p.slice(0, -1);
594
+ return p;
595
+ };
596
+ async function getBlogSitemapEntries(opts) {
597
+ const baseUrl = trimTrailingSlash2(opts.siteUrl);
598
+ const pathPrefix = normalizePathPrefix2(opts.pathPrefix ?? "/blog");
599
+ const blogs = await listBlogs(
600
+ { status: "PUBLISHED", language: opts.language },
601
+ {
602
+ apiKey: opts.apiKey,
603
+ apiUrl: opts.apiUrl,
604
+ revalidate: opts.revalidate
605
+ }
606
+ );
607
+ return blogs.map((blog) => ({
608
+ url: `${baseUrl}${pathPrefix}/${blog.slug}`,
609
+ lastModified: new Date(blog.published_at)
610
+ }));
611
+ }
612
+
613
+ export {
614
+ generateBlogMetadata,
615
+ generateBlogIndexMetadata,
616
+ DefaultHeading,
617
+ DefaultParagraph,
618
+ DefaultBulletList,
619
+ DefaultOrderedList,
620
+ DefaultBlockquote,
621
+ DefaultCodeBlock,
622
+ DefaultImage,
623
+ DefaultDivider,
624
+ DefaultMedia,
625
+ BlockRenderer,
626
+ BlogRenderer,
627
+ BlogDetail,
628
+ JsonLdGraph,
629
+ BlogJsonLd,
630
+ BlogPage,
631
+ generateBlogPageMetadata,
632
+ getBlog,
633
+ listBlogs,
634
+ getBlogSitemapEntries
635
+ };
636
+ //# sourceMappingURL=chunk-BXEQ6QKM.js.map