@fullstackdatasolutions/articles 0.9.0 → 0.11.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +243 -0
  2. package/README.md +226 -29
  3. package/dist/index.cjs +635 -274
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +165 -56
  6. package/dist/index.d.ts +165 -56
  7. package/dist/index.js +614 -250
  8. package/dist/index.js.map +1 -1
  9. package/dist/nextjs.cjs +40 -5
  10. package/dist/nextjs.cjs.map +1 -1
  11. package/dist/nextjs.d.cts +72 -0
  12. package/dist/nextjs.d.ts +72 -0
  13. package/dist/nextjs.js +40 -5
  14. package/dist/nextjs.js.map +1 -1
  15. package/dist/server.cjs +280 -16
  16. package/dist/server.cjs.map +1 -1
  17. package/dist/server.d.cts +92 -3
  18. package/dist/server.d.ts +92 -3
  19. package/dist/server.js +269 -16
  20. package/dist/server.js.map +1 -1
  21. package/package.json +8 -5
  22. package/src/ArticleDetailHero.tsx +27 -2
  23. package/src/ArticleSchemas.tsx +27 -27
  24. package/src/AuthorArticlesPage.tsx +60 -0
  25. package/src/AuthorCard.tsx +112 -0
  26. package/src/AuthorDetailHero.tsx +56 -0
  27. package/src/Breadcrumb.tsx +78 -0
  28. package/src/CategoryArticlesPage.tsx +62 -11
  29. package/src/__tests__/ArticleDetailHero.test.tsx +21 -1
  30. package/src/__tests__/ArticleSchemas.test.tsx +47 -2
  31. package/src/__tests__/AuthorArticlesPage.test.tsx +74 -0
  32. package/src/__tests__/AuthorCard.test.tsx +98 -0
  33. package/src/__tests__/AuthorDetailHero.test.tsx +51 -0
  34. package/src/__tests__/CategoryArticlesPage.test.tsx +31 -5
  35. package/src/__tests__/articlesConfig.test.ts +20 -1
  36. package/src/__tests__/authorUtils.test.ts +89 -0
  37. package/src/__tests__/renderMdx.test.tsx +113 -0
  38. package/src/__tests__/seoUtils-authors.test.ts +160 -0
  39. package/src/__tests__/seoUtils.test.ts +4 -0
  40. package/src/__tests__/server-articles.test.ts +159 -2
  41. package/src/articleTypes.ts +33 -0
  42. package/src/articlesConfig.ts +68 -0
  43. package/src/authorUtils.ts +95 -0
  44. package/src/index.ts +32 -9
  45. package/src/renderMdx.tsx +8 -2
  46. package/src/seoUtils.ts +226 -7
  47. package/src/server-articles.ts +98 -10
  48. package/src/server.ts +19 -1
package/dist/index.cjs CHANGED
@@ -81,6 +81,11 @@ __export(src_exports, {
81
81
  ArticleTOC: () => ArticleTOC,
82
82
  ArticlesHero: () => ArticlesHero,
83
83
  ArticlesPage: () => ArticlesPage,
84
+ AuthorArticlesPage: () => AuthorArticlesPage,
85
+ AuthorCard: () => AuthorCard,
86
+ AuthorDetailHero: () => AuthorDetailHero,
87
+ AuthorSocialLinks: () => AuthorSocialLinks,
88
+ Breadcrumb: () => Breadcrumb,
84
89
  BreadcrumbSchema: () => BreadcrumbSchema,
85
90
  CategoryArticlesPage: () => CategoryArticlesPage,
86
91
  CollectionPageSchema: () => CollectionPageSchema,
@@ -96,6 +101,8 @@ __export(src_exports, {
96
101
  LatestArticles: () => LatestArticles,
97
102
  LatestArticlesSection: () => LatestArticlesSection,
98
103
  ScrollToTop: () => ScrollToTop,
104
+ breadcrumbsAreEnabled: () => breadcrumbsAreEnabled,
105
+ getBreadcrumbsConfig: () => getBreadcrumbsConfig,
99
106
  useArticles: () => useArticles
100
107
  });
101
108
  module.exports = __toCommonJS(src_exports);
@@ -150,44 +157,177 @@ function ArticleCategoryGrid({ categories, pageSize = 8 }) {
150
157
  ] }) });
151
158
  }
152
159
 
153
- // src/ArticleSchemas.tsx
160
+ // src/authorUtils.ts
161
+ function getAuthorUrl(author) {
162
+ var _a;
163
+ return (_a = author.url) != null ? _a : `/articles/authors/${author.slug}`;
164
+ }
165
+ function getAuthorAvatar(author, config) {
166
+ if (!author.avatar) return void 0;
167
+ if (author.avatar.startsWith("http://") || author.avatar.startsWith("https://")) {
168
+ return author.avatar;
169
+ }
170
+ const path = `/articles/authors/${author.slug}/${author.avatar.replace(/^\/+/, "")}`;
171
+ if (!config) return path;
172
+ return `${config.siteUrl.replace(/\/$/, "")}${path}`;
173
+ }
174
+ function getAuthorSameAs(author) {
175
+ return getAuthorSocialLinks(author).map((link) => link.href);
176
+ }
177
+ function normalizeHandle(value) {
178
+ return value.replace(/^@/, "");
179
+ }
180
+ function normalizeUrl(value, baseUrl) {
181
+ if (value.startsWith("http://") || value.startsWith("https://")) return value;
182
+ if (!baseUrl) return value;
183
+ return `${baseUrl}${normalizeHandle(value)}`;
184
+ }
185
+ function getConfiguredSocialLinks(social) {
186
+ var _a, _b;
187
+ return [
188
+ { label: "Website", href: (_a = social.website) != null ? _a : "" },
189
+ {
190
+ label: "Facebook",
191
+ href: social.facebook ? normalizeUrl(social.facebook, "https://www.facebook.com/") : ""
192
+ },
193
+ {
194
+ label: "Twitter",
195
+ href: social.twitter ? normalizeUrl(social.twitter, "https://twitter.com/") : ""
196
+ },
197
+ { label: "X", href: social.x ? normalizeUrl(social.x, "https://x.com/") : "" },
198
+ {
199
+ label: "LinkedIn",
200
+ href: social.linkedin ? normalizeUrl(social.linkedin, "https://www.linkedin.com/in/") : ""
201
+ },
202
+ {
203
+ label: "Instagram",
204
+ href: social.instagram ? normalizeUrl(social.instagram, "https://www.instagram.com/") : ""
205
+ },
206
+ {
207
+ label: "YouTube",
208
+ href: social.youtube ? normalizeUrl(social.youtube, "https://www.youtube.com/") : ""
209
+ },
210
+ {
211
+ label: "TikTok",
212
+ href: social.tiktok ? normalizeUrl(social.tiktok, "https://www.tiktok.com/@") : ""
213
+ },
214
+ {
215
+ label: "GitHub",
216
+ href: social.github ? normalizeUrl(social.github, "https://github.com/") : ""
217
+ },
218
+ {
219
+ label: "Bluesky",
220
+ href: social.bluesky ? normalizeUrl(social.bluesky, "https://bsky.app/profile/") : ""
221
+ },
222
+ {
223
+ label: "Threads",
224
+ href: social.threads ? normalizeUrl(social.threads, "https://www.threads.net/@") : ""
225
+ },
226
+ { label: "Mastodon", href: social.mastodon ? normalizeUrl(social.mastodon) : "" },
227
+ {
228
+ label: "Medium",
229
+ href: social.medium ? normalizeUrl(social.medium, "https://medium.com/@") : ""
230
+ },
231
+ { label: "Newsletter", href: (_b = social.newsletter) != null ? _b : "" }
232
+ ];
233
+ }
234
+ function getAuthorSocialLinks(author) {
235
+ var _a;
236
+ const social = author.social;
237
+ if (!social) return [];
238
+ const configuredLinks = getConfiguredSocialLinks(social);
239
+ const otherLinks = Object.entries((_a = social.other) != null ? _a : {}).map(([label, href]) => ({ label, href }));
240
+ return [...configuredLinks, ...otherLinks].filter((link) => link.href.trim().length > 0);
241
+ }
242
+
243
+ // src/Breadcrumb.tsx
244
+ var import_link2 = __toESM(require("next/link"), 1);
154
245
  var import_jsx_runtime2 = require("react/jsx-runtime");
246
+ function buildBreadcrumbSchema(items) {
247
+ return {
248
+ "@context": "https://schema.org",
249
+ "@type": "BreadcrumbList",
250
+ itemListElement: items.map((item, index) => __spreadValues({
251
+ "@type": "ListItem",
252
+ position: index + 1,
253
+ name: item.name
254
+ }, item.url && { item: item.url }))
255
+ };
256
+ }
257
+ function getDisplayItems(items) {
258
+ if (items.length <= 4) return [...items];
259
+ return [items[0], { name: "..." }, ...items.slice(-2)];
260
+ }
261
+ function Breadcrumb({
262
+ items,
263
+ className = "",
264
+ showSchema = true,
265
+ separator = ">"
266
+ }) {
267
+ if (items.length === 0) return null;
268
+ const displayItems = getDisplayItems(items);
269
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
270
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
271
+ "nav",
272
+ {
273
+ "aria-label": "Breadcrumb",
274
+ className: `border-b border-border bg-background/80 px-4 py-3 text-sm text-muted-foreground ${className}`,
275
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ol", { className: "mx-auto flex max-w-7xl items-center gap-2 overflow-hidden", children: displayItems.map((item, index) => {
276
+ const isLast = index === displayItems.length - 1;
277
+ const key = `${item.name}-${index}`;
278
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "flex min-w-0 items-center gap-2", children: [
279
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "aria-hidden": "true", children: separator }),
280
+ item.url && !isLast ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_link2.default, { href: item.url, className: "truncate hover:text-foreground", children: item.name }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "truncate", "aria-current": isLast ? "page" : void 0, children: item.name })
281
+ ] }, key);
282
+ }) })
283
+ }
284
+ ),
285
+ showSchema && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
286
+ "script",
287
+ {
288
+ type: "application/ld+json",
289
+ dangerouslySetInnerHTML: { __html: JSON.stringify(buildBreadcrumbSchema(items)) }
290
+ }
291
+ )
292
+ ] });
293
+ }
294
+ function BreadcrumbSchema({ items }) {
295
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Breadcrumb, { items, showSchema: true, className: "sr-only" });
296
+ }
297
+
298
+ // src/ArticleSchemas.tsx
299
+ var import_jsx_runtime3 = require("react/jsx-runtime");
300
+ function getPersonSchemas(article, authors) {
301
+ let resolvedAuthors = [];
302
+ if (authors == null ? void 0 : authors.length) {
303
+ resolvedAuthors = [...authors];
304
+ } else if (article.author) {
305
+ resolvedAuthors = [{ name: article.author, slug: "", bio: "" }];
306
+ }
307
+ return resolvedAuthors.map((author) => __spreadValues(__spreadValues({
308
+ "@type": "Person",
309
+ name: author.name
310
+ }, author.url && { url: author.url }), getAuthorSameAs(author).length > 0 && { sameAs: getAuthorSameAs(author) }));
311
+ }
155
312
  function ArticleSchema({
156
313
  article,
157
314
  articleUrl,
158
315
  siteName,
159
- showAuthor = true
316
+ showAuthor = true,
317
+ authors
160
318
  }) {
319
+ const personSchemas = getPersonSchemas(article, authors);
161
320
  const schema = __spreadProps(__spreadValues(__spreadValues({
162
321
  "@context": "https://schema.org",
163
322
  "@type": "Article",
164
323
  headline: article.title,
165
324
  description: article.excerpt,
166
325
  image: article.featuredImage
167
- }, article.date && { datePublished: new Date(article.date).toISOString() }), showAuthor && { author: { "@type": "Person", name: article.author } }), {
326
+ }, article.date && { datePublished: new Date(article.date).toISOString() }), showAuthor && personSchemas.length > 0 && { author: personSchemas }), {
168
327
  publisher: { "@type": "Organization", name: siteName },
169
328
  mainEntityOfPage: { "@type": "WebPage", "@id": articleUrl }
170
329
  });
171
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
172
- "script",
173
- {
174
- type: "application/ld+json",
175
- dangerouslySetInnerHTML: { __html: JSON.stringify(schema) }
176
- }
177
- );
178
- }
179
- function BreadcrumbSchema({ items }) {
180
- const schema = {
181
- "@context": "https://schema.org",
182
- "@type": "BreadcrumbList",
183
- itemListElement: items.map((item, index) => ({
184
- "@type": "ListItem",
185
- position: index + 1,
186
- name: item.name,
187
- item: item.url
188
- }))
189
- };
190
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
330
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
191
331
  "script",
192
332
  {
193
333
  type: "application/ld+json",
@@ -200,32 +340,34 @@ function ArticleSEO({
200
340
  articleUrl,
201
341
  siteName,
202
342
  siteLogo,
203
- showAuthor = true
343
+ showAuthor = true,
344
+ authors
204
345
  }) {
205
346
  const publishedAt = article.date ? new Date(article.date).toISOString() : void 0;
206
347
  const modifiedAt = article.lastmod ? new Date(article.lastmod).toISOString() : publishedAt;
348
+ const personSchemas = getPersonSchemas(article, authors);
207
349
  const structuredData = __spreadValues(__spreadProps(__spreadValues(__spreadValues(__spreadValues({
208
350
  "@context": "https://schema.org",
209
351
  "@type": article.articleType || "Article",
210
352
  mainEntityOfPage: { "@type": "WebPage", "@id": articleUrl },
211
353
  headline: article.title,
212
354
  image: article.featuredImage ? { "@type": "ImageObject", url: article.featuredImage } : void 0
213
- }, publishedAt && { datePublished: publishedAt }), modifiedAt && { dateModified: modifiedAt }), showAuthor && { author: { "@type": "Person", name: article.author } }), {
355
+ }, publishedAt && { datePublished: publishedAt }), modifiedAt && { dateModified: modifiedAt }), showAuthor && personSchemas.length > 0 && { author: personSchemas }), {
214
356
  publisher: __spreadValues({
215
357
  "@type": "Organization",
216
358
  name: siteName
217
359
  }, siteLogo && { logo: { "@type": "ImageObject", url: siteLogo } }),
218
360
  description: article.excerpt
219
361
  }), article.series && { isPartOf: { "@type": "Blog", name: article.series } });
220
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
221
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
362
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
363
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
222
364
  "script",
223
365
  {
224
366
  type: "application/ld+json",
225
367
  dangerouslySetInnerHTML: { __html: JSON.stringify(structuredData) }
226
368
  }
227
369
  ),
228
- article.faq && article.faq.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
370
+ article.faq && article.faq.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
229
371
  "script",
230
372
  {
231
373
  type: "application/ld+json",
@@ -242,7 +384,7 @@ function ArticleSEO({
242
384
  }
243
385
  }
244
386
  ),
245
- article.howTo && article.howTo.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
387
+ article.howTo && article.howTo.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
246
388
  "script",
247
389
  {
248
390
  type: "application/ld+json",
@@ -272,7 +414,7 @@ function FAQPageSchema({ items }) {
272
414
  acceptedAnswer: { "@type": "Answer", text: answer }
273
415
  }))
274
416
  };
275
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
417
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
276
418
  "script",
277
419
  {
278
420
  type: "application/ld+json",
@@ -294,7 +436,7 @@ function CollectionPageSchema({
294
436
  url,
295
437
  numberOfItems: articleCount
296
438
  };
297
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
439
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
298
440
  "script",
299
441
  {
300
442
  type: "application/ld+json",
@@ -305,17 +447,17 @@ function CollectionPageSchema({
305
447
 
306
448
  // src/ArticleSearchBar.tsx
307
449
  var import_lucide_react = require("lucide-react");
308
- var import_jsx_runtime3 = require("react/jsx-runtime");
450
+ var import_jsx_runtime4 = require("react/jsx-runtime");
309
451
  function ArticleSearchBar({
310
452
  value,
311
453
  onChange,
312
454
  disabled,
313
455
  resultCount
314
456
  }) {
315
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("section", { className: "py-8 bg-background border-b border-border", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8", children: [
316
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative", children: [
317
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-5 w-5" }),
318
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
457
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { className: "py-8 bg-background border-b border-border", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8", children: [
458
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative", children: [
459
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-5 w-5" }),
460
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
319
461
  "input",
320
462
  {
321
463
  type: "text",
@@ -326,44 +468,44 @@ function ArticleSearchBar({
326
468
  className: "flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 pl-10 pr-10 py-3 text-lg"
327
469
  }
328
470
  ),
329
- value && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
471
+ value && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
330
472
  "button",
331
473
  {
332
474
  type: "button",
333
475
  onClick: () => onChange(""),
334
476
  "aria-label": "Clear search",
335
477
  className: "absolute right-3 top-1/2 transform -translate-y-1/2 text-muted-foreground hover:text-foreground",
336
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.X, { className: "h-5 w-5" })
478
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.X, { className: "h-5 w-5" })
337
479
  }
338
480
  )
339
481
  ] }),
340
- value && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mt-2 text-sm text-muted-foreground", children: resultCount === 0 ? "No articles found matching your search." : `Found ${resultCount} article${resultCount === 1 ? "" : "s"} matching "${value}"` })
482
+ value && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mt-2 text-sm text-muted-foreground", children: resultCount === 0 ? "No articles found matching your search." : `Found ${resultCount} article${resultCount === 1 ? "" : "s"} matching "${value}"` })
341
483
  ] }) });
342
484
  }
343
485
 
344
486
  // src/ArticlesHero.tsx
345
- var import_link2 = __toESM(require("next/link"), 1);
346
- var import_jsx_runtime4 = require("react/jsx-runtime");
487
+ var import_link3 = __toESM(require("next/link"), 1);
488
+ var import_jsx_runtime5 = require("react/jsx-runtime");
347
489
  var DEFAULT_TITLE = "Vox Populus Insights";
348
490
  var DEFAULT_DESCRIPTION = "Expert analysis, campaign strategies, and voter engagement insights from the frontlines of democracy.";
349
491
  function ArticlesHero({
350
492
  title = DEFAULT_TITLE,
351
493
  description = DEFAULT_DESCRIPTION
352
494
  }) {
353
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { className: "bg-linear-to-r from-gray-50 to-gray-100 py-16 md:py-24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "max-w-3xl mx-auto text-center", children: [
354
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "text-4xl md:text-5xl font-bold text-foreground mb-6", children: title }),
355
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-xl text-muted-foreground mb-8", children: description }),
356
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col sm:flex-row gap-4 justify-center", children: [
357
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
358
- import_link2.default,
495
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("section", { className: "bg-linear-to-r from-gray-50 to-gray-100 py-16 md:py-24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "max-w-3xl mx-auto text-center", children: [
496
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { className: "text-4xl md:text-5xl font-bold text-foreground mb-6", children: title }),
497
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xl text-muted-foreground mb-8", children: description }),
498
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col sm:flex-row gap-4 justify-center", children: [
499
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
500
+ import_link3.default,
359
501
  {
360
502
  href: "#latest",
361
503
  className: "inline-flex items-center justify-center px-4 py-2 bg-primary hover:bg-primary/90 text-primary-foreground rounded-md font-medium text-sm transition-colors",
362
504
  children: "Browse Latest Articles"
363
505
  }
364
506
  ),
365
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
366
- import_link2.default,
507
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
508
+ import_link3.default,
367
509
  {
368
510
  href: "/contact",
369
511
  className: "inline-flex items-center justify-center px-4 py-2 border border-primary text-primary hover:bg-primary/10 rounded-md font-medium text-sm transition-colors",
@@ -375,44 +517,44 @@ function ArticlesHero({
375
517
  }
376
518
 
377
519
  // src/FeaturedArticle.tsx
378
- var import_link3 = __toESM(require("next/link"), 1);
520
+ var import_link4 = __toESM(require("next/link"), 1);
379
521
  var import_image2 = __toESM(require("next/image"), 1);
380
522
  var import_lucide_react2 = require("lucide-react");
381
- var import_jsx_runtime5 = require("react/jsx-runtime");
523
+ var import_jsx_runtime6 = require("react/jsx-runtime");
382
524
  function FeaturedArticle({ article, showAuthor = true }) {
383
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("section", { className: "py-16 bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "grid lg:grid-cols-2 gap-12 items-center", children: [
384
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
385
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "inline-block bg-primary/10 text-primary text-sm font-medium px-3 py-1 rounded-full mb-4", children: "FEATURED ARTICLE" }),
386
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "text-3xl font-bold text-foreground mb-4", children: article.title }),
387
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-lg text-muted-foreground mb-6", children: article.excerpt }),
388
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-6 text-sm text-muted-foreground mb-6", children: [
389
- article.date && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
390
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.Calendar, { className: "h-4 w-4" }),
391
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: article.date })
525
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("section", { className: "py-16 bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "grid lg:grid-cols-2 gap-12 items-center", children: [
526
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
527
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "inline-block bg-primary/10 text-primary text-sm font-medium px-3 py-1 rounded-full mb-4", children: "FEATURED ARTICLE" }),
528
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "text-3xl font-bold text-foreground mb-4", children: article.title }),
529
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-lg text-muted-foreground mb-6", children: article.excerpt }),
530
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-6 text-sm text-muted-foreground mb-6", children: [
531
+ article.date && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
532
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Calendar, { className: "h-4 w-4" }),
533
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: article.date })
392
534
  ] }),
393
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
394
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.Clock, { className: "h-4 w-4" }),
395
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: article.readTime })
535
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
536
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Clock, { className: "h-4 w-4" }),
537
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: article.readTime })
396
538
  ] }),
397
- showAuthor && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
398
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.User, { className: "h-4 w-4" }),
399
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: article.author })
539
+ showAuthor && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
540
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.User, { className: "h-4 w-4" }),
541
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: article.author })
400
542
  ] })
401
543
  ] }),
402
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
403
- import_link3.default,
544
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
545
+ import_link4.default,
404
546
  {
405
547
  href: `/articles/${article.slug}`,
406
548
  className: "inline-flex items-center justify-center px-4 py-2 bg-primary hover:bg-primary/90 text-primary-foreground rounded-md font-medium text-sm transition-colors",
407
549
  children: [
408
550
  "Read Full Article",
409
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.ArrowRight, { className: "ml-2 h-4 w-4" })
551
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.ArrowRight, { className: "ml-2 h-4 w-4" })
410
552
  ]
411
553
  }
412
554
  )
413
555
  ] }),
414
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "bg-card rounded-lg p-8", children: [
415
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
556
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "bg-card rounded-lg p-8", children: [
557
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
416
558
  import_image2.default,
417
559
  {
418
560
  src: article.featuredImage,
@@ -422,7 +564,7 @@ function FeaturedArticle({ article, showAuthor = true }) {
422
564
  className: "w-full h-64 object-cover rounded-lg mb-4"
423
565
  }
424
566
  ),
425
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "bg-primary/10 text-primary text-xs font-medium px-2 py-1 rounded", children: article.category }) })
567
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "bg-primary/10 text-primary text-xs font-medium px-2 py-1 rounded", children: article.category }) })
426
568
  ] })
427
569
  ] }) }) });
428
570
  }
@@ -435,12 +577,12 @@ var import_react2 = require("react");
435
577
 
436
578
  // src/ArticleCard.tsx
437
579
  var import_image3 = __toESM(require("next/image"), 1);
438
- var import_link4 = __toESM(require("next/link"), 1);
580
+ var import_link5 = __toESM(require("next/link"), 1);
439
581
  var import_lucide_react3 = require("lucide-react");
440
- var import_jsx_runtime6 = require("react/jsx-runtime");
582
+ var import_jsx_runtime7 = require("react/jsx-runtime");
441
583
  function ArticleCard({ article }) {
442
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rounded-lg border border-border bg-card text-card-foreground shadow-sm hover:shadow-lg transition-shadow duration-300", children: [
443
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
584
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rounded-lg border border-border bg-card text-card-foreground shadow-sm hover:shadow-lg transition-shadow duration-300", children: [
585
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
444
586
  import_image3.default,
445
587
  {
446
588
  src: article.featuredImage,
@@ -450,35 +592,35 @@ function ArticleCard({ article }) {
450
592
  height: 200
451
593
  }
452
594
  ) }),
453
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "p-6", children: [
454
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex gap-2 mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "bg-primary/10 text-primary text-xs font-medium px-2 py-1 rounded", children: article.category }) }),
455
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: "text-lg font-semibold leading-none tracking-tight mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
456
- import_link4.default,
595
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "p-6", children: [
596
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex gap-2 mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "bg-primary/10 text-primary text-xs font-medium px-2 py-1 rounded", children: article.category }) }),
597
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "text-lg font-semibold leading-none tracking-tight mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
598
+ import_link5.default,
457
599
  {
458
600
  href: `/articles/${article.slug}`,
459
601
  className: "hover:text-indigo-600 transition-colors",
460
602
  children: article.title
461
603
  }
462
604
  ) }),
463
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-muted-foreground mb-4 line-clamp-3", children: article.excerpt }),
464
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between text-sm text-muted-foreground border-t pt-4", children: [
465
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-3", children: [
466
- article.date && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
467
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.Calendar, { className: "h-3 w-3" }),
468
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: article.date })
605
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-muted-foreground mb-4 line-clamp-3", children: article.excerpt }),
606
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between text-sm text-muted-foreground border-t pt-4", children: [
607
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-3", children: [
608
+ article.date && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
609
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Calendar, { className: "h-3 w-3" }),
610
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: article.date })
469
611
  ] }),
470
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
471
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.Clock, { className: "h-3 w-3" }),
472
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: article.readTime })
612
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
613
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Clock, { className: "h-3 w-3" }),
614
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: article.readTime })
473
615
  ] })
474
616
  ] }),
475
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
476
- import_link4.default,
617
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
618
+ import_link5.default,
477
619
  {
478
620
  href: `/articles/${article.slug}`,
479
621
  className: "inline-flex items-center justify-center h-8 w-8 p-0 rounded-md hover:bg-accent transition-colors",
480
622
  "aria-label": `Read ${article.title}`,
481
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.ArrowRight, { className: "h-4 w-4" })
623
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.ArrowRight, { className: "h-4 w-4" })
482
624
  }
483
625
  )
484
626
  ] })
@@ -487,7 +629,7 @@ function ArticleCard({ article }) {
487
629
  }
488
630
 
489
631
  // src/LatestArticles.tsx
490
- var import_jsx_runtime7 = require("react/jsx-runtime");
632
+ var import_jsx_runtime8 = require("react/jsx-runtime");
491
633
  function LatestArticles({ articles, pageSize }) {
492
634
  const [visibleCount, setVisibleCount] = (0, import_react2.useState)(pageSize);
493
635
  (0, import_react2.useEffect)(() => {
@@ -495,9 +637,9 @@ function LatestArticles({ articles, pageSize }) {
495
637
  }, [articles, pageSize]);
496
638
  const visible = articles.slice(0, visibleCount);
497
639
  const hasMore = visibleCount < articles.length;
498
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
499
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-8", children: visible.map((article) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArticleCard, { article }, article.slug)) }),
500
- hasMore && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-10 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
640
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
641
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-8", children: visible.map((article) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArticleCard, { article }, article.slug)) }),
642
+ hasMore && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mt-10 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
501
643
  "button",
502
644
  {
503
645
  type: "button",
@@ -510,14 +652,14 @@ function LatestArticles({ articles, pageSize }) {
510
652
  }
511
653
 
512
654
  // src/LatestArticlesSection.tsx
513
- var import_jsx_runtime8 = require("react/jsx-runtime");
655
+ var import_jsx_runtime9 = require("react/jsx-runtime");
514
656
  function DescriptionText({
515
657
  searchQuery,
516
658
  count
517
659
  }) {
518
660
  const pluralSuffix = count === 1 ? "" : "s";
519
661
  const text = searchQuery ? `Found ${count} article${pluralSuffix} matching your search.` : "Stay informed with our latest insights on voter engagement, campaign strategies, and civic technology.";
520
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-lg text-muted-foreground", children: text });
662
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-lg text-muted-foreground", children: text });
521
663
  }
522
664
  function LatestArticlesSection({
523
665
  articles,
@@ -525,20 +667,20 @@ function LatestArticlesSection({
525
667
  onClearSearch,
526
668
  pageSize = 6
527
669
  }) {
528
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("section", { id: "latest", className: "py-16 bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
529
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "text-center mb-12", children: [
530
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { className: "text-3xl font-bold text-foreground mb-4", children: searchQuery ? "Search Results" : "Latest Articles" }),
531
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DescriptionText, { searchQuery, count: articles.length })
670
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("section", { id: "latest", className: "py-16 bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
671
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-center mb-12", children: [
672
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h2", { className: "text-3xl font-bold text-foreground mb-4", children: searchQuery ? "Search Results" : "Latest Articles" }),
673
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DescriptionText, { searchQuery, count: articles.length })
532
674
  ] }),
533
- articles.length === 0 && searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "text-center py-12", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "max-w-md mx-auto", children: [
534
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react4.Search, { className: "h-12 w-12 text-muted-foreground mx-auto mb-4" }),
535
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "text-lg font-semibold text-foreground mb-2", children: "No articles found" }),
536
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { className: "text-muted-foreground mb-4", children: [
675
+ articles.length === 0 && searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-center py-12", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "max-w-md mx-auto", children: [
676
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react4.Search, { className: "h-12 w-12 text-muted-foreground mx-auto mb-4" }),
677
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "text-lg font-semibold text-foreground mb-2", children: "No articles found" }),
678
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "text-muted-foreground mb-4", children: [
537
679
  `We couldn't find any articles matching "`,
538
680
  searchQuery,
539
681
  '". Try adjusting your search terms.'
540
682
  ] }),
541
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
683
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
542
684
  "button",
543
685
  {
544
686
  type: "button",
@@ -547,7 +689,7 @@ function LatestArticlesSection({
547
689
  children: "Clear search"
548
690
  }
549
691
  )
550
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LatestArticles, { articles, pageSize }, searchQuery)
692
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LatestArticles, { articles, pageSize }, searchQuery)
551
693
  ] }) });
552
694
  }
553
695
 
@@ -561,6 +703,15 @@ var DEFAULT_LAYOUT = [
561
703
  "latest",
562
704
  "categories"
563
705
  ];
706
+ function breadcrumbsAreEnabled(config) {
707
+ var _a;
708
+ return config.breadcrumbs !== false && ((_a = config.breadcrumbs) == null ? void 0 : _a.show) !== false;
709
+ }
710
+ function getBreadcrumbsConfig(config) {
711
+ var _a;
712
+ if (config.breadcrumbs === false) return {};
713
+ return (_a = config.breadcrumbs) != null ? _a : {};
714
+ }
564
715
 
565
716
  // src/useArticles.ts
566
717
  var import_react3 = require("react");
@@ -631,7 +782,7 @@ function useArticles() {
631
782
  }
632
783
 
633
784
  // src/ArticlesPage.tsx
634
- var import_jsx_runtime9 = require("react/jsx-runtime");
785
+ var import_jsx_runtime10 = require("react/jsx-runtime");
635
786
  function buildThemeVars(theme) {
636
787
  if (!theme) return {};
637
788
  const vars = {};
@@ -664,7 +815,7 @@ function renderSection(section, ctx, config) {
664
815
  } = ctx;
665
816
  switch (section) {
666
817
  case "hero":
667
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
818
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
668
819
  ArticlesHero,
669
820
  {
670
821
  title: (_a = config.hero) == null ? void 0 : _a.title,
@@ -673,7 +824,7 @@ function renderSection(section, ctx, config) {
673
824
  "hero"
674
825
  );
675
826
  case "search":
676
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
827
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
677
828
  ArticleSearchBar,
678
829
  {
679
830
  value: searchQuery,
@@ -684,7 +835,7 @@ function renderSection(section, ctx, config) {
684
835
  "search"
685
836
  );
686
837
  case "featured":
687
- return articles.length > 0 && !searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
838
+ return articles.length > 0 && !searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
688
839
  FeaturedArticle,
689
840
  {
690
841
  article: articles[0],
@@ -694,16 +845,16 @@ function renderSection(section, ctx, config) {
694
845
  ) : null;
695
846
  case "latest":
696
847
  if (loading && articles.length === 0) {
697
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center py-24", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-center", children: [
698
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4" }),
699
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-muted-foreground", children: "Loading articles..." })
848
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center py-24", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "text-center", children: [
849
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4" }),
850
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-muted-foreground", children: "Loading articles..." })
700
851
  ] }) }) }, "latest");
701
852
  }
702
853
  if (error) {
703
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "bg-red-50 border border-red-200 rounded-lg p-6 max-w-md text-center", children: [
704
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "text-lg font-semibold text-red-800 mb-2", children: "Error Loading Articles" }),
705
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-red-600 mb-4", children: error }),
706
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
854
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "bg-red-50 border border-red-200 rounded-lg p-6 max-w-md text-center", children: [
855
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-lg font-semibold text-red-800 mb-2", children: "Error Loading Articles" }),
856
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-red-600 mb-4", children: error }),
857
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
707
858
  "button",
708
859
  {
709
860
  type: "button",
@@ -714,7 +865,7 @@ function renderSection(section, ctx, config) {
714
865
  )
715
866
  ] }) }) }, "latest");
716
867
  }
717
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
868
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
718
869
  LatestArticlesSection,
719
870
  {
720
871
  articles: displayedArticles,
@@ -725,7 +876,7 @@ function renderSection(section, ctx, config) {
725
876
  "latest"
726
877
  );
727
878
  case "categories":
728
- return searchQuery ? null : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
879
+ return searchQuery ? null : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
729
880
  ArticleCategoryGrid,
730
881
  {
731
882
  categories,
@@ -749,9 +900,9 @@ function ArticlesPage({ config }) {
749
900
  const articlesWithoutFeatured = hasFeatured ? state.articles.slice(1) : state.articles;
750
901
  const displayedArticles = state.searchQuery ? state.articles : articlesWithoutFeatured;
751
902
  const ctx = __spreadProps(__spreadValues({}, state), { displayedArticles, pageSize, categoriesPageSize });
752
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: themeVars, children: [
903
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: themeVars, children: [
753
904
  layout.map((section) => renderSection(section, ctx, config)),
754
- state.articles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
905
+ state.articles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
755
906
  CollectionPageSchema,
756
907
  {
757
908
  title: `Articles | ${config.siteName}`,
@@ -764,10 +915,11 @@ function ArticlesPage({ config }) {
764
915
  }
765
916
 
766
917
  // src/ArticleDetailHero.tsx
918
+ var import_react4 = require("react");
767
919
  var import_image4 = __toESM(require("next/image"), 1);
768
- var import_link5 = __toESM(require("next/link"), 1);
920
+ var import_link6 = __toESM(require("next/link"), 1);
769
921
  var import_lucide_react5 = require("lucide-react");
770
- var import_jsx_runtime10 = require("react/jsx-runtime");
922
+ var import_jsx_runtime11 = require("react/jsx-runtime");
771
923
  function toSlug(cat) {
772
924
  return cat.toLowerCase().replaceAll(/\s+/g, "-").replaceAll(/[^a-z0-9-]/g, "");
773
925
  }
@@ -775,9 +927,12 @@ function ArticleDetailHero({
775
927
  article,
776
928
  categoryBasePath = "/articles/category",
777
929
  showDate = false,
778
- showAuthor = true
930
+ showAuthor = true,
931
+ authors = []
779
932
  }) {
780
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
933
+ const showConfiguredAuthors = showAuthor && authors.length > 0;
934
+ const showLegacyAuthor = showAuthor && authors.length === 0 && article.author.trim().length > 0;
935
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
781
936
  "section",
782
937
  {
783
938
  style: {
@@ -789,7 +944,7 @@ function ArticleDetailHero({
789
944
  overflow: "hidden"
790
945
  },
791
946
  children: [
792
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
947
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
793
948
  import_image4.default,
794
949
  {
795
950
  src: article.featuredImage,
@@ -801,7 +956,7 @@ function ArticleDetailHero({
801
956
  priority: true
802
957
  }
803
958
  ),
804
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
959
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
805
960
  "div",
806
961
  {
807
962
  style: {
@@ -811,7 +966,7 @@ function ArticleDetailHero({
811
966
  }
812
967
  }
813
968
  ),
814
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
969
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
815
970
  "div",
816
971
  {
817
972
  style: {
@@ -825,7 +980,7 @@ function ArticleDetailHero({
825
980
  width: "100%"
826
981
  },
827
982
  children: [
828
- article.categories && article.categories.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
983
+ article.categories && article.categories.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
829
984
  "div",
830
985
  {
831
986
  style: {
@@ -836,15 +991,15 @@ function ArticleDetailHero({
836
991
  marginBottom: "1rem"
837
992
  },
838
993
  children: article.categories.slice(0, 4).map(
839
- (cat) => categoryBasePath ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
840
- import_link5.default,
994
+ (cat) => categoryBasePath ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
995
+ import_link6.default,
841
996
  {
842
997
  href: `${categoryBasePath}/${toSlug(cat)}`,
843
998
  className: "inline-block bg-white/20 text-white text-sm font-medium px-3 py-1 rounded-full hover:bg-white/30 transition-colors",
844
999
  children: cat
845
1000
  },
846
1001
  cat
847
- ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1002
+ ) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
848
1003
  "span",
849
1004
  {
850
1005
  className: "inline-block bg-white/20 text-white text-sm font-medium px-3 py-1 rounded-full",
@@ -855,8 +1010,8 @@ function ArticleDetailHero({
855
1010
  )
856
1011
  }
857
1012
  ),
858
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { className: "text-4xl md:text-5xl font-bold mb-4", children: article.title }),
859
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1013
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { className: "text-4xl md:text-5xl font-bold mb-4", children: article.title }),
1014
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
860
1015
  "div",
861
1016
  {
862
1017
  style: {
@@ -868,17 +1023,35 @@ function ArticleDetailHero({
868
1023
  color: "rgba(255,255,255,0.8)"
869
1024
  },
870
1025
  children: [
871
- showDate && article.date && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
872
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.Calendar, { className: "h-4 w-4" }),
873
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: article.date })
1026
+ showDate && article.date && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1027
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react5.Calendar, { className: "h-4 w-4" }),
1028
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: article.date })
874
1029
  ] }),
875
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
876
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.Clock, { className: "h-4 w-4" }),
877
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: article.readTime })
1030
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1031
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react5.Clock, { className: "h-4 w-4" }),
1032
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: article.readTime })
878
1033
  ] }),
879
- showAuthor && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
880
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react5.User, { className: "h-4 w-4" }),
881
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
1034
+ showConfiguredAuthors && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1035
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react5.User, { className: "h-4 w-4" }),
1036
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { children: [
1037
+ "By",
1038
+ " ",
1039
+ authors.map((author, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react4.Fragment, { children: [
1040
+ index > 0 && ", ",
1041
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1042
+ import_link6.default,
1043
+ {
1044
+ href: `/articles/authors/${author.slug}`,
1045
+ className: "font-medium text-white underline-offset-4 hover:underline",
1046
+ children: author.name
1047
+ }
1048
+ )
1049
+ ] }, author.slug))
1050
+ ] })
1051
+ ] }),
1052
+ showLegacyAuthor && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1053
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react5.User, { className: "h-4 w-4" }),
1054
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { children: [
882
1055
  "By ",
883
1056
  article.author
884
1057
  ] })
@@ -896,8 +1069,8 @@ function ArticleDetailHero({
896
1069
 
897
1070
  // src/CategoryArticlesPage.tsx
898
1071
  var import_image5 = __toESM(require("next/image"), 1);
899
- var import_link6 = __toESM(require("next/link"), 1);
900
- var import_jsx_runtime11 = require("react/jsx-runtime");
1072
+ var import_link7 = __toESM(require("next/link"), 1);
1073
+ var import_jsx_runtime12 = require("react/jsx-runtime");
901
1074
  function getCategoryDescription(config, slug, categoryName) {
902
1075
  var _a;
903
1076
  const raw = (_a = config.categoryDescriptions) == null ? void 0 : _a[slug];
@@ -905,6 +1078,40 @@ function getCategoryDescription(config, slug, categoryName) {
905
1078
  if (typeof raw === "string") return { short: raw };
906
1079
  return raw;
907
1080
  }
1081
+ function buildCategoryBreadcrumbItems(config, categoryName) {
1082
+ var _a;
1083
+ const siteUrl = config.siteUrl.replace(/\/$/, "");
1084
+ const breadcrumbConfig = getBreadcrumbsConfig(config);
1085
+ const trail = (_a = breadcrumbConfig.category) != null ? _a : ["home", "articles", "category"];
1086
+ return trail.flatMap(
1087
+ (entry) => {
1088
+ var _a2;
1089
+ return buildCategoryBreadcrumbEntry(entry, {
1090
+ categoryName,
1091
+ siteUrl,
1092
+ labels: (_a2 = breadcrumbConfig.labels) != null ? _a2 : {}
1093
+ });
1094
+ }
1095
+ );
1096
+ }
1097
+ function isCustomBreadcrumbItem(entry) {
1098
+ return typeof entry === "object" && entry !== null && "name" in entry && "url" in entry;
1099
+ }
1100
+ function resolveCustomBreadcrumbItem(item, siteUrl) {
1101
+ if (item.url.startsWith("/")) return { name: item.name, url: `${siteUrl}${item.url}` };
1102
+ return { name: item.name, url: item.url };
1103
+ }
1104
+ function buildCategoryBreadcrumbEntry(entry, context) {
1105
+ var _a, _b;
1106
+ if (isCustomBreadcrumbItem(entry)) {
1107
+ return [resolveCustomBreadcrumbItem(entry, context.siteUrl)];
1108
+ }
1109
+ if (entry === "home") return [{ name: (_a = context.labels.home) != null ? _a : "Home", url: context.siteUrl }];
1110
+ if (entry === "articles") {
1111
+ return [{ name: (_b = context.labels.articles) != null ? _b : "Articles", url: `${context.siteUrl}/articles` }];
1112
+ }
1113
+ return [{ name: context.categoryName }];
1114
+ }
908
1115
  function CategoryArticlesPage({ category, articles, config }) {
909
1116
  var _a;
910
1117
  if (articles.length === 0) return null;
@@ -912,19 +1119,18 @@ function CategoryArticlesPage({ category, articles, config }) {
912
1119
  const heroImage = articles[0].featuredImage;
913
1120
  const description = getCategoryDescription(config, category, categoryName);
914
1121
  const pageSize = (_a = config.pageSize) != null ? _a : DEFAULT_PAGE_SIZE;
915
- const siteUrl = config.siteUrl.replace(/\/$/, "");
916
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
917
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
918
- BreadcrumbSchema,
1122
+ const breadcrumbConfig = getBreadcrumbsConfig(config);
1123
+ const breadcrumbItems = buildCategoryBreadcrumbItems(config, categoryName);
1124
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
1125
+ breadcrumbsAreEnabled(config) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1126
+ Breadcrumb,
919
1127
  {
920
- items: [
921
- { name: "Home", url: siteUrl },
922
- { name: "Articles", url: `${siteUrl}/articles` },
923
- { name: categoryName, url: `${siteUrl}/articles/category/${category}` }
924
- ]
1128
+ items: breadcrumbItems,
1129
+ separator: breadcrumbConfig.separator,
1130
+ showSchema: breadcrumbConfig.showSchema !== false
925
1131
  }
926
1132
  ),
927
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1133
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
928
1134
  "section",
929
1135
  {
930
1136
  style: {
@@ -936,7 +1142,7 @@ function CategoryArticlesPage({ category, articles, config }) {
936
1142
  overflow: "hidden"
937
1143
  },
938
1144
  children: [
939
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1145
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
940
1146
  import_image5.default,
941
1147
  {
942
1148
  src: heroImage,
@@ -947,8 +1153,8 @@ function CategoryArticlesPage({ category, articles, config }) {
947
1153
  priority: true
948
1154
  }
949
1155
  ),
950
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { position: "absolute", inset: 0, backgroundColor: "rgba(0,0,0,0.6)" } }),
951
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1156
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { position: "absolute", inset: 0, backgroundColor: "rgba(0,0,0,0.6)" } }),
1157
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
952
1158
  "div",
953
1159
  {
954
1160
  style: {
@@ -959,10 +1165,10 @@ function CategoryArticlesPage({ category, articles, config }) {
959
1165
  padding: "0 1rem"
960
1166
  },
961
1167
  children: [
962
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-sm font-semibold uppercase tracking-widest mb-3 opacity-80", children: "Category" }),
963
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { className: "text-4xl md:text-5xl font-bold mb-3", children: categoryName }),
964
- description.long && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-lg opacity-90 max-w-2xl mx-auto mt-2", children: description.long }),
965
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("p", { className: "text-lg opacity-70 mt-2", children: [
1168
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-semibold uppercase tracking-widest mb-3 opacity-80", children: "Category" }),
1169
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h1", { className: "text-4xl md:text-5xl font-bold mb-3", children: categoryName }),
1170
+ description.long && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-lg opacity-90 max-w-2xl mx-auto mt-2", children: description.long }),
1171
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "text-lg opacity-70 mt-2", children: [
966
1172
  articles.length,
967
1173
  " article",
968
1174
  articles.length === 1 ? "" : "s"
@@ -973,22 +1179,170 @@ function CategoryArticlesPage({ category, articles, config }) {
973
1179
  ]
974
1180
  }
975
1181
  ),
976
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("section", { className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
977
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mb-8 flex items-center justify-between", children: [
978
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_link6.default, { href: "/articles", className: "text-sm text-primary hover:underline", children: "\u2190 All Articles" }),
979
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-sm text-muted-foreground", children: description.short })
1182
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("section", { className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
1183
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-8 flex items-center justify-between", children: [
1184
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_link7.default, { href: "/articles", className: "text-sm text-primary hover:underline", children: "\u2190 All Articles" }),
1185
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: description.short })
980
1186
  ] }),
981
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LatestArticles, { articles, pageSize })
1187
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LatestArticles, { articles, pageSize })
982
1188
  ] }) })
983
1189
  ] });
984
1190
  }
985
1191
 
986
- // src/ArticleSocialShare.tsx
987
- var import_react4 = require("react");
1192
+ // src/AuthorArticlesPage.tsx
1193
+ var import_link8 = __toESM(require("next/link"), 1);
1194
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1195
+ function getPersonSchema(author, config, articleCount) {
1196
+ var _a, _b;
1197
+ return __spreadProps(__spreadValues(__spreadValues({
1198
+ "@context": "https://schema.org",
1199
+ "@type": "Person",
1200
+ name: author.name,
1201
+ description: author.bio,
1202
+ url: (_a = author.url) != null ? _a : getAuthorUrl(author)
1203
+ }, getAuthorAvatar(author, config) && { image: getAuthorAvatar(author, config) }), getAuthorSameAs(author).length > 0 && { sameAs: getAuthorSameAs(author) }), {
1204
+ knowsAbout: config.siteName,
1205
+ mainEntityOfPage: (_b = author.url) != null ? _b : `${config.siteUrl.replace(/\/$/, "")}/articles/authors/${author.slug}`,
1206
+ interactionStatistic: {
1207
+ "@type": "InteractionCounter",
1208
+ interactionType: "https://schema.org/WriteAction",
1209
+ userInteractionCount: articleCount
1210
+ }
1211
+ });
1212
+ }
1213
+ function AuthorArticlesPage({ author, articles, config }) {
1214
+ var _a;
1215
+ const pageSize = (_a = config.pageSize) != null ? _a : DEFAULT_PAGE_SIZE;
1216
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1217
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1218
+ "script",
1219
+ {
1220
+ type: "application/ld+json",
1221
+ dangerouslySetInnerHTML: {
1222
+ __html: JSON.stringify(getPersonSchema(author, config, articles.length))
1223
+ }
1224
+ }
1225
+ ),
1226
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("section", { className: "bg-background py-16", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8", children: [
1227
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "mb-8 flex items-center justify-between gap-4", children: [
1228
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_link8.default, { href: "/articles", className: "text-sm text-primary hover:underline", children: "All Articles" }),
1229
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "text-sm text-muted-foreground", children: [
1230
+ "Articles by ",
1231
+ author.name
1232
+ ] })
1233
+ ] }),
1234
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LatestArticles, { articles, pageSize })
1235
+ ] }) })
1236
+ ] });
1237
+ }
1238
+
1239
+ // src/AuthorCard.tsx
1240
+ var import_image6 = __toESM(require("next/image"), 1);
1241
+ var import_link9 = __toESM(require("next/link"), 1);
988
1242
  var import_lucide_react6 = require("lucide-react");
989
- var import_jsx_runtime12 = require("react/jsx-runtime");
1243
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1244
+ function getInitials(name) {
1245
+ return name.split(" ").filter(Boolean).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
1246
+ }
1247
+ function AuthorCard({
1248
+ author,
1249
+ linkToPage = true,
1250
+ showBio = false,
1251
+ showSocial = false
1252
+ }) {
1253
+ const avatar = getAuthorAvatar(author);
1254
+ const name = linkToPage ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_link9.default, { href: getAuthorUrl(author), className: "font-medium text-foreground hover:text-primary", children: author.name }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-medium text-foreground", children: author.name });
1255
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-start gap-3 rounded-lg border border-border bg-card p-4 text-card-foreground", children: [
1256
+ avatar ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1257
+ import_image6.default,
1258
+ {
1259
+ src: avatar,
1260
+ alt: author.name,
1261
+ width: 48,
1262
+ height: 48,
1263
+ className: "h-12 w-12 rounded-full object-cover"
1264
+ }
1265
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex h-12 w-12 shrink-0 items-center justify-center rounded-full bg-muted text-sm font-semibold text-muted-foreground", children: getInitials(author.name) }),
1266
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "min-w-0 flex-1", children: [
1267
+ name,
1268
+ showBio && author.bio && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 line-clamp-2 text-sm text-muted-foreground", children: author.bio }),
1269
+ showSocial && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AuthorSocialLinks, { author })
1270
+ ] })
1271
+ ] });
1272
+ }
1273
+ var SOCIAL_ICONS = {
1274
+ Website: import_lucide_react6.Globe,
1275
+ Facebook: import_lucide_react6.Facebook,
1276
+ Twitter: import_lucide_react6.Twitter,
1277
+ X: import_lucide_react6.Twitter,
1278
+ LinkedIn: import_lucide_react6.Linkedin,
1279
+ Instagram: import_lucide_react6.Instagram,
1280
+ YouTube: import_lucide_react6.Youtube,
1281
+ GitHub: import_lucide_react6.Github,
1282
+ Newsletter: import_lucide_react6.Mail
1283
+ };
1284
+ function getSocialIcon(label) {
1285
+ var _a;
1286
+ return (_a = SOCIAL_ICONS[label]) != null ? _a : import_lucide_react6.MessageCircle;
1287
+ }
1288
+ function AuthorSocialLinks({ author }) {
1289
+ const links = getAuthorSocialLinks(author);
1290
+ if (links.length === 0) return null;
1291
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mt-3 flex items-center gap-2", children: links.map(({ href, label }) => {
1292
+ const Icon = getSocialIcon(label);
1293
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1294
+ import_link9.default,
1295
+ {
1296
+ href,
1297
+ className: "inline-flex h-8 w-8 items-center justify-center rounded-md border border-border text-muted-foreground hover:bg-accent hover:text-accent-foreground",
1298
+ "aria-label": `${author.name} on ${label}`,
1299
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Icon, { className: "h-4 w-4" })
1300
+ },
1301
+ `${label}-${href}`
1302
+ );
1303
+ }) });
1304
+ }
1305
+
1306
+ // src/AuthorDetailHero.tsx
1307
+ var import_image7 = __toESM(require("next/image"), 1);
1308
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1309
+ function getInitials2(name) {
1310
+ return name.split(" ").filter(Boolean).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
1311
+ }
1312
+ function AuthorDetailHero({ author, articleCount }) {
1313
+ const avatar = getAuthorAvatar(author);
1314
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("section", { className: "bg-muted/40 py-16", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "mx-auto flex max-w-4xl flex-col items-center gap-6 px-4 text-center sm:px-6 lg:px-8", children: [
1315
+ avatar ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1316
+ import_image7.default,
1317
+ {
1318
+ src: avatar,
1319
+ alt: author.name,
1320
+ width: 120,
1321
+ height: 120,
1322
+ className: "h-28 w-28 rounded-full object-cover",
1323
+ priority: true
1324
+ }
1325
+ ) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex h-28 w-28 items-center justify-center rounded-full bg-card text-3xl font-semibold text-muted-foreground shadow-sm", children: getInitials2(author.name) }),
1326
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
1327
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mb-3 text-sm font-semibold uppercase tracking-widest text-muted-foreground", children: "Author" }),
1328
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h1", { className: "text-4xl font-bold text-foreground md:text-5xl", children: author.name }),
1329
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mx-auto mt-4 max-w-2xl text-lg text-muted-foreground", children: author.bio }),
1330
+ typeof articleCount === "number" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { className: "mt-3 text-sm text-muted-foreground", children: [
1331
+ articleCount,
1332
+ " article",
1333
+ articleCount === 1 ? "" : "s"
1334
+ ] })
1335
+ ] }),
1336
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AuthorSocialLinks, { author })
1337
+ ] }) });
1338
+ }
1339
+
1340
+ // src/ArticleSocialShare.tsx
1341
+ var import_react5 = require("react");
1342
+ var import_lucide_react7 = require("lucide-react");
1343
+ var import_jsx_runtime16 = require("react/jsx-runtime");
990
1344
  function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
991
- const [copied, setCopied] = (0, import_react4.useState)(false);
1345
+ const [copied, setCopied] = (0, import_react5.useState)(false);
992
1346
  const encodedTitle = encodeURIComponent(title);
993
1347
  const encodedUrl = encodeURIComponent(url);
994
1348
  const encodedExcerpt = encodeURIComponent(excerpt || "");
@@ -1013,84 +1367,84 @@ function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
1013
1367
  globalThis.open(shareUrl, "_blank", "width=600,height=400,scrollbars=yes,resizable=yes");
1014
1368
  };
1015
1369
  const btnClass = "inline-flex items-center gap-2 px-3 py-1.5 text-sm rounded-md border border-border bg-background text-foreground hover:bg-primary/10 hover:border-primary hover:text-primary transition-colors cursor-pointer";
1016
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "border-t border-border pt-8 mt-8", children: [
1017
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-2 mb-4", children: [
1018
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.Share2, { className: "h-5 w-5 text-muted-foreground" }),
1019
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: "Share this article" })
1370
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "border-t border-border pt-8 mt-8", children: [
1371
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-2 mb-4", children: [
1372
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Share2, { className: "h-5 w-5 text-muted-foreground" }),
1373
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: "Share this article" })
1020
1374
  ] }),
1021
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap gap-2", children: [
1022
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.linkedin), children: [
1023
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.Users, { className: "h-4 w-4" }),
1375
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-wrap gap-2", children: [
1376
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.linkedin), children: [
1377
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Users, { className: "h-4 w-4" }),
1024
1378
  "LinkedIn"
1025
1379
  ] }),
1026
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.facebook), children: [
1027
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "text-xs font-bold", children: "f" }),
1380
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.facebook), children: [
1381
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs font-bold", children: "f" }),
1028
1382
  " Facebook"
1029
1383
  ] }),
1030
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.twitter), children: [
1031
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.MessageCircle, { className: "h-4 w-4" }),
1384
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.twitter), children: [
1385
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.MessageCircle, { className: "h-4 w-4" }),
1032
1386
  "Twitter"
1033
1387
  ] }),
1034
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.reddit), children: [
1035
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.FileText, { className: "h-4 w-4" }),
1388
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.reddit), children: [
1389
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.FileText, { className: "h-4 w-4" }),
1036
1390
  "Reddit"
1037
1391
  ] }),
1038
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.whatsapp), children: [
1039
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.MessageCircle, { className: "h-4 w-4" }),
1392
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.whatsapp), children: [
1393
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.MessageCircle, { className: "h-4 w-4" }),
1040
1394
  "WhatsApp"
1041
1395
  ] }),
1042
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.telegram), children: [
1043
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.MessageCircle, { className: "h-4 w-4" }),
1396
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.telegram), children: [
1397
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.MessageCircle, { className: "h-4 w-4" }),
1044
1398
  "Telegram"
1045
1399
  ] }),
1046
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("a", { className: btnClass, href: shareLinks.email, children: [
1047
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.Mail, { className: "h-4 w-4" }),
1400
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("a", { className: btnClass, href: shareLinks.email, children: [
1401
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Mail, { className: "h-4 w-4" }),
1048
1402
  "Email"
1049
1403
  ] }),
1050
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { className: btnClass, onClick: copyToClipboard, children: [
1051
- copied ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.Check, { className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.Copy, { className: "h-4 w-4" }),
1404
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { className: btnClass, onClick: copyToClipboard, children: [
1405
+ copied ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Check, { className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Copy, { className: "h-4 w-4" }),
1052
1406
  copied ? "Copied!" : "Copy Link"
1053
1407
  ] })
1054
1408
  ] }),
1055
- shareMessage && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground mt-3", children: shareMessage })
1409
+ shareMessage && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-sm text-muted-foreground mt-3", children: shareMessage })
1056
1410
  ] });
1057
1411
  }
1058
1412
 
1059
1413
  // src/ArticleNavigation.tsx
1060
- var import_link7 = __toESM(require("next/link"), 1);
1061
- var import_lucide_react7 = require("lucide-react");
1062
- var import_jsx_runtime13 = require("react/jsx-runtime");
1414
+ var import_link10 = __toESM(require("next/link"), 1);
1415
+ var import_lucide_react8 = require("lucide-react");
1416
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1063
1417
  function truncateTitle(title, maxLength = 60) {
1064
1418
  return title.length > maxLength ? `${title.substring(0, maxLength)}...` : title;
1065
1419
  }
1066
1420
  function ArticleNavigation({ previous, next, basePath }) {
1067
1421
  if (!previous && !next) return null;
1068
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("nav", { className: "mt-12 pt-8 border-t border-border", "aria-label": "Article navigation", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex justify-between gap-4", children: [
1069
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex-1 min-w-0", children: previous && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1070
- import_link7.default,
1422
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("nav", { className: "mt-12 pt-8 border-t border-border", "aria-label": "Article navigation", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex justify-between gap-4", children: [
1423
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 min-w-0", children: previous && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1424
+ import_link10.default,
1071
1425
  {
1072
1426
  href: `${basePath}/${previous.slug}`,
1073
1427
  className: "group flex items-center gap-3 p-4 rounded-lg border border-border hover:border-primary/20 hover:bg-muted/50 transition-colors",
1074
1428
  children: [
1075
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.ChevronLeft, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" }),
1076
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "min-w-0 flex-1", children: [
1077
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-sm text-muted-foreground mb-1", children: "Previous Article" }),
1078
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "font-medium text-foreground truncate", title: previous.title, children: truncateTitle(previous.title) })
1429
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.ChevronLeft, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" }),
1430
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "min-w-0 flex-1", children: [
1431
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "text-sm text-muted-foreground mb-1", children: "Previous Article" }),
1432
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "font-medium text-foreground truncate", title: previous.title, children: truncateTitle(previous.title) })
1079
1433
  ] })
1080
1434
  ]
1081
1435
  }
1082
1436
  ) }),
1083
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex-1 min-w-0", children: next && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1084
- import_link7.default,
1437
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 min-w-0", children: next && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1438
+ import_link10.default,
1085
1439
  {
1086
1440
  href: `${basePath}/${next.slug}`,
1087
1441
  className: "group flex items-center justify-end gap-3 p-4 rounded-lg border border-border hover:border-primary/20 hover:bg-muted/50 transition-colors",
1088
1442
  children: [
1089
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "min-w-0 flex-1 text-right", children: [
1090
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-sm text-muted-foreground mb-1", children: "Next Article" }),
1091
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "font-medium text-foreground truncate", title: next.title, children: truncateTitle(next.title) })
1443
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "min-w-0 flex-1 text-right", children: [
1444
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "text-sm text-muted-foreground mb-1", children: "Next Article" }),
1445
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "font-medium text-foreground truncate", title: next.title, children: truncateTitle(next.title) })
1092
1446
  ] }),
1093
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.ChevronRight, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" })
1447
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.ChevronRight, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" })
1094
1448
  ]
1095
1449
  }
1096
1450
  ) })
@@ -1098,9 +1452,9 @@ function ArticleNavigation({ previous, next, basePath }) {
1098
1452
  }
1099
1453
 
1100
1454
  // src/ArticleBackLink.tsx
1101
- var import_link8 = __toESM(require("next/link"), 1);
1102
- var import_lucide_react8 = require("lucide-react");
1103
- var import_jsx_runtime14 = require("react/jsx-runtime");
1455
+ var import_link11 = __toESM(require("next/link"), 1);
1456
+ var import_lucide_react9 = require("lucide-react");
1457
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1104
1458
  function ArticleBackLink({
1105
1459
  config,
1106
1460
  href = "/articles",
@@ -1108,13 +1462,13 @@ function ArticleBackLink({
1108
1462
  className
1109
1463
  }) {
1110
1464
  if (config.showBackToArticles === false) return null;
1111
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1112
- import_link8.default,
1465
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1466
+ import_link11.default,
1113
1467
  {
1114
1468
  href,
1115
1469
  className: className != null ? className : "inline-flex items-center gap-2 mb-6 -ml-3 px-3 py-2 rounded-md text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors",
1116
1470
  children: [
1117
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react8.ArrowLeft, { className: "h-4 w-4" }),
1471
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react9.ArrowLeft, { className: "h-4 w-4" }),
1118
1472
  label
1119
1473
  ]
1120
1474
  }
@@ -1122,17 +1476,17 @@ function ArticleBackLink({
1122
1476
  }
1123
1477
 
1124
1478
  // src/ArticleTOC.tsx
1125
- var import_jsx_runtime15 = require("react/jsx-runtime");
1479
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1126
1480
  function ArticleTOC({ toc, className }) {
1127
1481
  if (!toc.length) return null;
1128
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1482
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1129
1483
  "nav",
1130
1484
  {
1131
1485
  "aria-label": "Table of contents",
1132
1486
  className: `mb-8 rounded-lg border border-border bg-muted/40 px-6 py-4 ${className != null ? className : ""}`,
1133
1487
  children: [
1134
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: "On this page" }),
1135
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { className: "space-y-1 text-sm", children: toc.map((item) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("li", { style: { paddingLeft: `${Math.max(0, item.depth - 2) * 1}rem` }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1488
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: "On this page" }),
1489
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ul", { className: "space-y-1 text-sm", children: toc.map((item) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("li", { style: { paddingLeft: `${Math.max(0, item.depth - 2) * 1}rem` }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1136
1490
  "a",
1137
1491
  {
1138
1492
  href: `#${item.id}`,
@@ -1146,35 +1500,35 @@ function ArticleTOC({ toc, className }) {
1146
1500
  }
1147
1501
 
1148
1502
  // src/ScrollToTop.tsx
1149
- var import_react5 = require("react");
1150
- var import_lucide_react9 = require("lucide-react");
1151
- var import_jsx_runtime16 = require("react/jsx-runtime");
1503
+ var import_react6 = require("react");
1504
+ var import_lucide_react10 = require("lucide-react");
1505
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1152
1506
  function ScrollToTop() {
1153
- const [visible, setVisible] = (0, import_react5.useState)(false);
1154
- (0, import_react5.useEffect)(() => {
1507
+ const [visible, setVisible] = (0, import_react6.useState)(false);
1508
+ (0, import_react6.useEffect)(() => {
1155
1509
  const onScroll = () => setVisible(globalThis.scrollY > 300);
1156
1510
  globalThis.addEventListener("scroll", onScroll, { passive: true });
1157
1511
  return () => globalThis.removeEventListener("scroll", onScroll);
1158
1512
  }, []);
1159
1513
  if (!visible) return null;
1160
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1514
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1161
1515
  "button",
1162
1516
  {
1163
1517
  "aria-label": "Scroll to top",
1164
1518
  onClick: () => globalThis.scrollTo({ top: 0, behavior: "smooth" }),
1165
1519
  className: "fixed bottom-8 right-8 z-50 rounded-full bg-primary p-2 shadow-md text-primary-foreground hover:bg-primary/90 transition-colors",
1166
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.ArrowUp, { className: "h-5 w-5" })
1520
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.ArrowUp, { className: "h-5 w-5" })
1167
1521
  }
1168
1522
  );
1169
1523
  }
1170
1524
 
1171
1525
  // src/CommentsSection.tsx
1172
- var import_react8 = require("next-auth/react");
1173
- var import_react9 = require("react");
1526
+ var import_react9 = require("next-auth/react");
1527
+ var import_react10 = require("react");
1174
1528
 
1175
1529
  // src/CommentForm.tsx
1176
- var import_react6 = require("react");
1177
- var import_jsx_runtime17 = require("react/jsx-runtime");
1530
+ var import_react7 = require("react");
1531
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1178
1532
  var MAX_LENGTH = 2e3;
1179
1533
  var WARN_THRESHOLD = 1800;
1180
1534
  function submitLabel(submitting, parentId) {
@@ -1182,9 +1536,9 @@ function submitLabel(submitting, parentId) {
1182
1536
  return parentId ? "Reply" : "Post comment";
1183
1537
  }
1184
1538
  function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
1185
- const [body, setBody] = (0, import_react6.useState)("");
1186
- const [submitting, setSubmitting] = (0, import_react6.useState)(false);
1187
- const [error, setError] = (0, import_react6.useState)(null);
1539
+ const [body, setBody] = (0, import_react7.useState)("");
1540
+ const [submitting, setSubmitting] = (0, import_react7.useState)(false);
1541
+ const [error, setError] = (0, import_react7.useState)(null);
1188
1542
  const remaining = MAX_LENGTH - body.length;
1189
1543
  function handleSubmit(e) {
1190
1544
  return __async(this, null, function* () {
@@ -1213,8 +1567,8 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
1213
1567
  }
1214
1568
  });
1215
1569
  }
1216
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-2", children: [
1217
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1570
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-2", children: [
1571
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1218
1572
  "textarea",
1219
1573
  {
1220
1574
  value: body,
@@ -1227,13 +1581,13 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
1227
1581
  "aria-label": parentId ? "Reply text" : "Comment text"
1228
1582
  }
1229
1583
  ),
1230
- remaining <= MAX_LENGTH - WARN_THRESHOLD && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("p", { className: `text-xs ${remaining < 0 ? "text-destructive" : "text-muted-foreground"}`, children: [
1584
+ remaining <= MAX_LENGTH - WARN_THRESHOLD && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("p", { className: `text-xs ${remaining < 0 ? "text-destructive" : "text-muted-foreground"}`, children: [
1231
1585
  remaining,
1232
1586
  " characters remaining"
1233
1587
  ] }),
1234
- error && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs text-destructive", children: error }),
1235
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex gap-2", children: [
1236
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1588
+ error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs text-destructive", children: error }),
1589
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex gap-2", children: [
1590
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1237
1591
  "button",
1238
1592
  {
1239
1593
  type: "submit",
@@ -1242,7 +1596,7 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
1242
1596
  children: submitLabel(submitting, parentId)
1243
1597
  }
1244
1598
  ),
1245
- onCancel && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1599
+ onCancel && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1246
1600
  "button",
1247
1601
  {
1248
1602
  type: "button",
@@ -1256,8 +1610,8 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
1256
1610
  }
1257
1611
 
1258
1612
  // src/CommentItem.tsx
1259
- var import_react7 = require("react");
1260
- var import_jsx_runtime18 = require("react/jsx-runtime");
1613
+ var import_react8 = require("react");
1614
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1261
1615
  function relativeTime(iso) {
1262
1616
  const diff = Date.now() - new Date(iso).getTime();
1263
1617
  const minutes = Math.floor(diff / 6e4);
@@ -1278,8 +1632,8 @@ function CommentItem({
1278
1632
  isReply = false,
1279
1633
  onRefresh
1280
1634
  }) {
1281
- const [showReplyForm, setShowReplyForm] = (0, import_react7.useState)(false);
1282
- const [deleting, setDeleting] = (0, import_react7.useState)(false);
1635
+ const [showReplyForm, setShowReplyForm] = (0, import_react8.useState)(false);
1636
+ const [deleting, setDeleting] = (0, import_react8.useState)(false);
1283
1637
  const replies = "replies" in comment ? comment.replies : [];
1284
1638
  const canReply = !isReply && !!currentUserId && !comment.isDeleted;
1285
1639
  const canDelete = !!currentUserId && currentUserId === comment.authorId && !comment.isDeleted;
@@ -1295,15 +1649,15 @@ function CommentItem({
1295
1649
  }
1296
1650
  });
1297
1651
  }
1298
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `${isReply ? "ml-8 border-l-2 border-border pl-4" : ""}`, children: [
1299
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "rounded-lg bg-muted/40 p-3 space-y-1", children: comment.isDeleted ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm italic text-muted-foreground", children: "Comment removed" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
1300
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
1301
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-sm font-medium text-foreground", children: comment.authorName }),
1302
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-xs text-muted-foreground", children: relativeTime(comment.createdAt) })
1652
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `${isReply ? "ml-8 border-l-2 border-border pl-4" : ""}`, children: [
1653
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "rounded-lg bg-muted/40 p-3 space-y-1", children: comment.isDeleted ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-sm italic text-muted-foreground", children: "Comment removed" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
1654
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
1655
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-sm font-medium text-foreground", children: comment.authorName }),
1656
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground", children: relativeTime(comment.createdAt) })
1303
1657
  ] }),
1304
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-foreground whitespace-pre-wrap break-words", children: comment.body }),
1305
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex gap-3 pt-1", children: [
1306
- canReply && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1658
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-sm text-foreground whitespace-pre-wrap break-words", children: comment.body }),
1659
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex gap-3 pt-1", children: [
1660
+ canReply && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1307
1661
  "button",
1308
1662
  {
1309
1663
  onClick: () => setShowReplyForm((v) => !v),
@@ -1311,7 +1665,7 @@ function CommentItem({
1311
1665
  children: showReplyForm ? "Cancel" : "Reply"
1312
1666
  }
1313
1667
  ),
1314
- canDelete && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1668
+ canDelete && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1315
1669
  "button",
1316
1670
  {
1317
1671
  onClick: handleDelete,
@@ -1322,7 +1676,7 @@ function CommentItem({
1322
1676
  )
1323
1677
  ] })
1324
1678
  ] }) }),
1325
- showReplyForm && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "mt-2 ml-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1679
+ showReplyForm && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "mt-2 ml-2", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1326
1680
  CommentForm,
1327
1681
  {
1328
1682
  articleSlug,
@@ -1334,7 +1688,7 @@ function CommentItem({
1334
1688
  onCancel: () => setShowReplyForm(false)
1335
1689
  }
1336
1690
  ) }),
1337
- replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "mt-2 space-y-2", children: replies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1691
+ replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "mt-2 space-y-2", children: replies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1338
1692
  CommentItem,
1339
1693
  {
1340
1694
  comment: __spreadProps(__spreadValues({}, reply), { replies: [] }),
@@ -1349,7 +1703,7 @@ function CommentItem({
1349
1703
  }
1350
1704
 
1351
1705
  // src/CommentThread.tsx
1352
- var import_jsx_runtime19 = require("react/jsx-runtime");
1706
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1353
1707
  function CommentThread({
1354
1708
  comments,
1355
1709
  articleSlug,
@@ -1357,9 +1711,9 @@ function CommentThread({
1357
1711
  onRefresh
1358
1712
  }) {
1359
1713
  if (comments.length === 0) {
1360
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm text-muted-foreground text-center py-6", children: "No comments yet. Be the first to share your thoughts." });
1714
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-sm text-muted-foreground text-center py-6", children: "No comments yet. Be the first to share your thoughts." });
1361
1715
  }
1362
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-4", children: comments.map((comment) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1716
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "space-y-4", children: comments.map((comment) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1363
1717
  CommentItem,
1364
1718
  {
1365
1719
  comment,
@@ -1372,17 +1726,17 @@ function CommentThread({
1372
1726
  }
1373
1727
 
1374
1728
  // src/CommentsSection.tsx
1375
- var import_jsx_runtime20 = require("react/jsx-runtime");
1729
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1376
1730
  function CommentsSection({ articleSlug, config }) {
1377
1731
  var _a, _b, _c, _d, _e, _f;
1378
- const { data: session, status } = (0, import_react8.useSession)();
1379
- const [comments, setComments] = (0, import_react9.useState)([]);
1380
- const [loading, setLoading] = (0, import_react9.useState)(true);
1381
- const [fetchError, setFetchError] = (0, import_react9.useState)(null);
1732
+ const { data: session, status } = (0, import_react9.useSession)();
1733
+ const [comments, setComments] = (0, import_react10.useState)([]);
1734
+ const [loading, setLoading] = (0, import_react10.useState)(true);
1735
+ const [fetchError, setFetchError] = (0, import_react10.useState)(null);
1382
1736
  const perArticleEnabled = (_b = (_a = config.perArticleOverride) == null ? void 0 : _a[articleSlug]) != null ? _b : true;
1383
1737
  const enabled = config.enabled && perArticleEnabled;
1384
1738
  const currentUserId = (_f = (_e = (_c = session == null ? void 0 : session.user) == null ? void 0 : _c.email) != null ? _e : (_d = session == null ? void 0 : session.user) == null ? void 0 : _d.name) != null ? _f : void 0;
1385
- const fetchComments = (0, import_react9.useCallback)(() => __async(this, null, function* () {
1739
+ const fetchComments = (0, import_react10.useCallback)(() => __async(this, null, function* () {
1386
1740
  setLoading(true);
1387
1741
  setFetchError(null);
1388
1742
  try {
@@ -1396,7 +1750,7 @@ function CommentsSection({ articleSlug, config }) {
1396
1750
  setLoading(false);
1397
1751
  }
1398
1752
  }), [articleSlug]);
1399
- (0, import_react9.useEffect)(() => {
1753
+ (0, import_react10.useEffect)(() => {
1400
1754
  if (enabled) {
1401
1755
  fetchComments().catch(() => void 0);
1402
1756
  }
@@ -1404,13 +1758,13 @@ function CommentsSection({ articleSlug, config }) {
1404
1758
  if (!enabled) return null;
1405
1759
  const count = comments.length;
1406
1760
  const label = count === 1 ? "1 comment" : `${count} comments`;
1407
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("section", { "aria-label": "Comments", className: "mt-12 pt-8 border-t border-border space-y-6", children: [
1408
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { className: "text-xl font-semibold text-foreground", children: loading ? "Comments" : label }),
1409
- status === "authenticated" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CommentForm, { articleSlug, onSuccess: fetchComments }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "text-sm text-muted-foreground", children: [
1410
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1761
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("section", { "aria-label": "Comments", className: "mt-12 pt-8 border-t border-border space-y-6", children: [
1762
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "text-xl font-semibold text-foreground", children: loading ? "Comments" : label }),
1763
+ status === "authenticated" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CommentForm, { articleSlug, onSuccess: fetchComments }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { className: "text-sm text-muted-foreground", children: [
1764
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1411
1765
  "button",
1412
1766
  {
1413
- onClick: () => (0, import_react8.signIn)(),
1767
+ onClick: () => (0, import_react9.signIn)(),
1414
1768
  className: "text-primary underline hover:no-underline focus:outline-none",
1415
1769
  children: "Sign in"
1416
1770
  }
@@ -1418,8 +1772,8 @@ function CommentsSection({ articleSlug, config }) {
1418
1772
  " ",
1419
1773
  "to join the discussion."
1420
1774
  ] }),
1421
- fetchError && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-destructive", children: fetchError }),
1422
- loading ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-muted-foreground", children: "Loading comments\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1775
+ fetchError && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm text-destructive", children: fetchError }),
1776
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm text-muted-foreground", children: "Loading comments\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1423
1777
  CommentThread,
1424
1778
  {
1425
1779
  comments,
@@ -1444,6 +1798,11 @@ function CommentsSection({ articleSlug, config }) {
1444
1798
  ArticleTOC,
1445
1799
  ArticlesHero,
1446
1800
  ArticlesPage,
1801
+ AuthorArticlesPage,
1802
+ AuthorCard,
1803
+ AuthorDetailHero,
1804
+ AuthorSocialLinks,
1805
+ Breadcrumb,
1447
1806
  BreadcrumbSchema,
1448
1807
  CategoryArticlesPage,
1449
1808
  CollectionPageSchema,
@@ -1459,6 +1818,8 @@ function CommentsSection({ articleSlug, config }) {
1459
1818
  LatestArticles,
1460
1819
  LatestArticlesSection,
1461
1820
  ScrollToTop,
1821
+ breadcrumbsAreEnabled,
1822
+ getBreadcrumbsConfig,
1462
1823
  useArticles
1463
1824
  });
1464
1825
  //# sourceMappingURL=index.cjs.map