@fullstackdatasolutions/articles 0.11.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +568 -6
- package/dist/index.cjs +970 -389
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +375 -21
- package/dist/index.d.ts +375 -21
- package/dist/index.js +954 -377
- package/dist/index.js.map +1 -1
- package/dist/nextjs.cjs +74 -6
- package/dist/nextjs.cjs.map +1 -1
- package/dist/nextjs.d.cts +141 -0
- package/dist/nextjs.d.ts +141 -0
- package/dist/nextjs.js +74 -6
- package/dist/nextjs.js.map +1 -1
- package/dist/server.cjs +665 -27
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +349 -3
- package/dist/server.d.ts +349 -3
- package/dist/server.js +643 -29
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/ArticleCard.tsx +37 -1
- package/src/ArticleContent.tsx +144 -5
- package/src/ArticleDetailHero.tsx +23 -0
- package/src/ArticleNavigation.tsx +32 -1
- package/src/ArticleSchemas.tsx +43 -39
- package/src/ArticleSocialShare.tsx +54 -10
- package/src/ArticlesPage.tsx +65 -7
- package/src/AuthorArticlesPage.tsx +308 -14
- package/src/AuthorCard.tsx +1 -1
- package/src/CategoryArticlesPage.tsx +34 -2
- package/src/LatestArticles.tsx +28 -1
- package/src/LatestArticlesSection.tsx +15 -1
- package/src/PaginationNav.tsx +78 -0
- package/src/RelatedArticlesSection.tsx +55 -0
- package/src/SeriesArticlesPage.tsx +66 -0
- package/src/__tests__/ArticleCard.test.tsx +63 -3
- package/src/__tests__/ArticleContent.test.tsx +143 -0
- package/src/__tests__/ArticleDetailHero.test.tsx +30 -0
- package/src/__tests__/ArticleNavigation.test.tsx +81 -3
- package/src/__tests__/ArticleSchemas.test.tsx +155 -81
- package/src/__tests__/ArticleSocialShare.test.tsx +54 -0
- package/src/__tests__/ArticlesPage.test.tsx +148 -0
- package/src/__tests__/AuthorArticlesPage.test.tsx +304 -3
- package/src/__tests__/CategoryArticlesPage.test.tsx +116 -1
- package/src/__tests__/LatestArticles.test.tsx +52 -0
- package/src/__tests__/LatestArticlesSection.test.tsx +28 -0
- package/src/__tests__/PaginationNav.test.tsx +73 -0
- package/src/__tests__/RelatedArticlesSection.test.tsx +132 -0
- package/src/__tests__/SeriesArticlesPage.test.tsx +121 -0
- package/src/__tests__/eventTracking.test.tsx +145 -0
- package/src/__tests__/events.test.ts +82 -0
- package/src/__tests__/markdown.test.ts +78 -1
- package/src/__tests__/pagination.test.ts +178 -0
- package/src/__tests__/seoUtils-authors.test.ts +37 -0
- package/src/__tests__/seoUtils.test.ts +246 -0
- package/src/__tests__/server-articles.test.ts +356 -1
- package/src/__tests__/useArticles.test.ts +28 -0
- package/src/__tests__/validateArticles.test.ts +312 -0
- package/src/articleTypes.ts +109 -0
- package/src/articlesConfig.ts +37 -1
- package/src/eventTracking.tsx +97 -0
- package/src/events.ts +105 -0
- package/src/index.ts +26 -1
- package/src/markdown.ts +41 -0
- package/src/pagination.ts +93 -0
- package/src/seoUtils.ts +198 -11
- package/src/server-articles.ts +199 -6
- package/src/server.ts +46 -2
- package/src/useArticles.ts +10 -5
- package/src/validateArticles.ts +260 -0
package/dist/index.js
CHANGED
|
@@ -230,43 +230,17 @@ function BreadcrumbSchema({ items }) {
|
|
|
230
230
|
|
|
231
231
|
// src/ArticleSchemas.tsx
|
|
232
232
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
233
|
-
function getPersonSchemas(article, authors) {
|
|
233
|
+
function getPersonSchemas(article, authors, config) {
|
|
234
234
|
let resolvedAuthors = [];
|
|
235
235
|
if (authors == null ? void 0 : authors.length) {
|
|
236
236
|
resolvedAuthors = [...authors];
|
|
237
237
|
} else if (article.author) {
|
|
238
238
|
resolvedAuthors = [{ name: article.author, slug: "", bio: "" }];
|
|
239
239
|
}
|
|
240
|
-
return resolvedAuthors.map((author) => __spreadValues(__spreadValues({
|
|
240
|
+
return resolvedAuthors.map((author) => __spreadValues(__spreadValues(__spreadValues({
|
|
241
241
|
"@type": "Person",
|
|
242
242
|
name: author.name
|
|
243
|
-
}, author.url && { url: author.url }), getAuthorSameAs(author).length > 0 && { sameAs: getAuthorSameAs(author) }));
|
|
244
|
-
}
|
|
245
|
-
function ArticleSchema({
|
|
246
|
-
article,
|
|
247
|
-
articleUrl,
|
|
248
|
-
siteName,
|
|
249
|
-
showAuthor = true,
|
|
250
|
-
authors
|
|
251
|
-
}) {
|
|
252
|
-
const personSchemas = getPersonSchemas(article, authors);
|
|
253
|
-
const schema = __spreadProps(__spreadValues(__spreadValues({
|
|
254
|
-
"@context": "https://schema.org",
|
|
255
|
-
"@type": "Article",
|
|
256
|
-
headline: article.title,
|
|
257
|
-
description: article.excerpt,
|
|
258
|
-
image: article.featuredImage
|
|
259
|
-
}, article.date && { datePublished: new Date(article.date).toISOString() }), showAuthor && personSchemas.length > 0 && { author: personSchemas }), {
|
|
260
|
-
publisher: { "@type": "Organization", name: siteName },
|
|
261
|
-
mainEntityOfPage: { "@type": "WebPage", "@id": articleUrl }
|
|
262
|
-
});
|
|
263
|
-
return /* @__PURE__ */ jsx3(
|
|
264
|
-
"script",
|
|
265
|
-
{
|
|
266
|
-
type: "application/ld+json",
|
|
267
|
-
dangerouslySetInnerHTML: { __html: JSON.stringify(schema) }
|
|
268
|
-
}
|
|
269
|
-
);
|
|
243
|
+
}, author.url && { url: author.url }), getAuthorAvatar(author, config) && { image: getAuthorAvatar(author, config) }), getAuthorSameAs(author).length > 0 && { sameAs: getAuthorSameAs(author) }));
|
|
270
244
|
}
|
|
271
245
|
function ArticleSEO({
|
|
272
246
|
article,
|
|
@@ -274,12 +248,13 @@ function ArticleSEO({
|
|
|
274
248
|
siteName,
|
|
275
249
|
siteLogo,
|
|
276
250
|
showAuthor = true,
|
|
277
|
-
authors
|
|
251
|
+
authors,
|
|
252
|
+
config
|
|
278
253
|
}) {
|
|
279
254
|
const publishedAt = article.date ? new Date(article.date).toISOString() : void 0;
|
|
280
255
|
const modifiedAt = article.lastmod ? new Date(article.lastmod).toISOString() : publishedAt;
|
|
281
|
-
const personSchemas = getPersonSchemas(article, authors);
|
|
282
|
-
const structuredData = __spreadValues(__spreadProps(__spreadValues(__spreadValues(__spreadValues({
|
|
256
|
+
const personSchemas = getPersonSchemas(article, authors, config);
|
|
257
|
+
const structuredData = __spreadValues(__spreadValues(__spreadValues(__spreadProps(__spreadValues(__spreadValues(__spreadValues({
|
|
283
258
|
"@context": "https://schema.org",
|
|
284
259
|
"@type": article.articleType || "Article",
|
|
285
260
|
mainEntityOfPage: { "@type": "WebPage", "@id": articleUrl },
|
|
@@ -290,8 +265,9 @@ function ArticleSEO({
|
|
|
290
265
|
"@type": "Organization",
|
|
291
266
|
name: siteName
|
|
292
267
|
}, siteLogo && { logo: { "@type": "ImageObject", url: siteLogo } }),
|
|
293
|
-
description: article.excerpt
|
|
294
|
-
|
|
268
|
+
description: article.excerpt,
|
|
269
|
+
articleSection: article.category
|
|
270
|
+
}), article.tags && article.tags.length > 0 && { keywords: article.tags.join(", ") }), article.wordCount !== void 0 && { wordCount: article.wordCount }), article.series && { isPartOf: { "@type": "Blog", name: article.series } });
|
|
295
271
|
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
296
272
|
/* @__PURE__ */ jsx3(
|
|
297
273
|
"script",
|
|
@@ -359,16 +335,27 @@ function CollectionPageSchema({
|
|
|
359
335
|
title,
|
|
360
336
|
description,
|
|
361
337
|
url,
|
|
362
|
-
articleCount
|
|
338
|
+
articleCount,
|
|
339
|
+
items
|
|
363
340
|
}) {
|
|
364
|
-
const schema = {
|
|
341
|
+
const schema = __spreadValues({
|
|
365
342
|
"@context": "https://schema.org",
|
|
366
343
|
"@type": "CollectionPage",
|
|
367
344
|
name: title,
|
|
368
345
|
description,
|
|
369
346
|
url,
|
|
370
347
|
numberOfItems: articleCount
|
|
371
|
-
}
|
|
348
|
+
}, items && items.length > 0 && {
|
|
349
|
+
mainEntity: {
|
|
350
|
+
"@type": "ItemList",
|
|
351
|
+
itemListElement: items.map((item) => ({
|
|
352
|
+
"@type": "ListItem",
|
|
353
|
+
position: item.position,
|
|
354
|
+
url: item.url,
|
|
355
|
+
name: item.name
|
|
356
|
+
}))
|
|
357
|
+
}
|
|
358
|
+
});
|
|
372
359
|
return /* @__PURE__ */ jsx3(
|
|
373
360
|
"script",
|
|
374
361
|
{
|
|
@@ -509,14 +496,102 @@ import { Search as Search2 } from "lucide-react";
|
|
|
509
496
|
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
510
497
|
|
|
511
498
|
// src/ArticleCard.tsx
|
|
499
|
+
import Image4 from "next/image";
|
|
500
|
+
import Link6 from "next/link";
|
|
501
|
+
import { ArrowRight as ArrowRight2, Calendar as Calendar2, Clock as Clock2 } from "lucide-react";
|
|
502
|
+
|
|
503
|
+
// src/AuthorCard.tsx
|
|
512
504
|
import Image3 from "next/image";
|
|
513
505
|
import Link5 from "next/link";
|
|
514
|
-
import {
|
|
506
|
+
import {
|
|
507
|
+
Facebook,
|
|
508
|
+
Github,
|
|
509
|
+
Globe,
|
|
510
|
+
Instagram,
|
|
511
|
+
Linkedin,
|
|
512
|
+
Mail,
|
|
513
|
+
MessageCircle,
|
|
514
|
+
Twitter,
|
|
515
|
+
Youtube
|
|
516
|
+
} from "lucide-react";
|
|
515
517
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
516
|
-
function
|
|
517
|
-
return
|
|
518
|
-
|
|
518
|
+
function getInitials(name) {
|
|
519
|
+
return name.split(" ").filter(Boolean).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
|
|
520
|
+
}
|
|
521
|
+
function AuthorCard({
|
|
522
|
+
author,
|
|
523
|
+
linkToPage = true,
|
|
524
|
+
showBio = false,
|
|
525
|
+
showSocial = false
|
|
526
|
+
}) {
|
|
527
|
+
const avatar = getAuthorAvatar(author);
|
|
528
|
+
const name = linkToPage ? /* @__PURE__ */ jsx7(Link5, { href: getAuthorUrl(author), className: "font-medium text-foreground hover:text-primary", children: author.name }) : /* @__PURE__ */ jsx7("span", { className: "font-medium text-foreground", children: author.name });
|
|
529
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-3 rounded-lg border border-border bg-card p-4 text-card-foreground", children: [
|
|
530
|
+
avatar ? /* @__PURE__ */ jsx7(
|
|
519
531
|
Image3,
|
|
532
|
+
{
|
|
533
|
+
src: avatar,
|
|
534
|
+
alt: author.name,
|
|
535
|
+
width: 48,
|
|
536
|
+
height: 48,
|
|
537
|
+
className: "h-12 w-12 rounded-full object-cover"
|
|
538
|
+
}
|
|
539
|
+
) : /* @__PURE__ */ jsx7("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) }),
|
|
540
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
541
|
+
name,
|
|
542
|
+
showBio && author.bio && /* @__PURE__ */ jsx7("p", { className: "mt-1 line-clamp-2 text-sm text-muted-foreground", children: author.bio }),
|
|
543
|
+
showSocial && /* @__PURE__ */ jsx7(AuthorSocialLinks, { author })
|
|
544
|
+
] })
|
|
545
|
+
] });
|
|
546
|
+
}
|
|
547
|
+
var SOCIAL_ICONS = {
|
|
548
|
+
Website: Globe,
|
|
549
|
+
Facebook,
|
|
550
|
+
Twitter,
|
|
551
|
+
X: Twitter,
|
|
552
|
+
LinkedIn: Linkedin,
|
|
553
|
+
Instagram,
|
|
554
|
+
YouTube: Youtube,
|
|
555
|
+
GitHub: Github,
|
|
556
|
+
Newsletter: Mail
|
|
557
|
+
};
|
|
558
|
+
function getSocialIcon(label) {
|
|
559
|
+
var _a;
|
|
560
|
+
return (_a = SOCIAL_ICONS[label]) != null ? _a : MessageCircle;
|
|
561
|
+
}
|
|
562
|
+
function AuthorSocialLinks({ author }) {
|
|
563
|
+
const links = getAuthorSocialLinks(author);
|
|
564
|
+
if (links.length === 0) return null;
|
|
565
|
+
return /* @__PURE__ */ jsx7("div", { className: "mt-3 flex items-center gap-2", children: links.map(({ href, label }) => {
|
|
566
|
+
const Icon = getSocialIcon(label);
|
|
567
|
+
return /* @__PURE__ */ jsx7(
|
|
568
|
+
Link5,
|
|
569
|
+
{
|
|
570
|
+
href,
|
|
571
|
+
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",
|
|
572
|
+
"aria-label": `${author.name} on ${label}`,
|
|
573
|
+
children: /* @__PURE__ */ jsx7(Icon, { className: "h-4 w-4" })
|
|
574
|
+
},
|
|
575
|
+
`${label}-${href}`
|
|
576
|
+
);
|
|
577
|
+
}) });
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// src/events.ts
|
|
581
|
+
function emitArticleEvent(handler, event) {
|
|
582
|
+
if (!handler) return;
|
|
583
|
+
try {
|
|
584
|
+
handler(__spreadProps(__spreadValues({}, event), { timestamp: Date.now() }));
|
|
585
|
+
} catch (e) {
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// src/ArticleCard.tsx
|
|
590
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
591
|
+
function ArticleCard({ article, config }) {
|
|
592
|
+
return /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border border-border bg-card text-card-foreground shadow-sm hover:shadow-lg transition-shadow duration-300", children: [
|
|
593
|
+
/* @__PURE__ */ jsx8("div", { className: "p-0", children: /* @__PURE__ */ jsx8(
|
|
594
|
+
Image4,
|
|
520
595
|
{
|
|
521
596
|
src: article.featuredImage,
|
|
522
597
|
alt: article.title,
|
|
@@ -525,35 +600,67 @@ function ArticleCard({ article }) {
|
|
|
525
600
|
height: 200
|
|
526
601
|
}
|
|
527
602
|
) }),
|
|
528
|
-
/* @__PURE__ */
|
|
529
|
-
/* @__PURE__ */
|
|
530
|
-
/* @__PURE__ */
|
|
531
|
-
|
|
603
|
+
/* @__PURE__ */ jsxs8("div", { className: "p-6", children: [
|
|
604
|
+
/* @__PURE__ */ jsx8("div", { className: "flex gap-2 mb-3", children: /* @__PURE__ */ jsx8("span", { className: "bg-primary/10 text-primary text-xs font-medium px-2 py-1 rounded", children: article.category }) }),
|
|
605
|
+
/* @__PURE__ */ jsx8("h3", { className: "text-lg font-semibold leading-none tracking-tight mb-2", children: /* @__PURE__ */ jsx8(
|
|
606
|
+
Link6,
|
|
532
607
|
{
|
|
533
608
|
href: `/articles/${article.slug}`,
|
|
534
609
|
className: "hover:text-indigo-600 transition-colors",
|
|
535
610
|
children: article.title
|
|
536
611
|
}
|
|
537
612
|
) }),
|
|
538
|
-
/* @__PURE__ */
|
|
539
|
-
/* @__PURE__ */
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
613
|
+
/* @__PURE__ */ jsx8("p", { className: "text-muted-foreground mb-4 line-clamp-3", children: article.excerpt }),
|
|
614
|
+
article.authorSlug && /* @__PURE__ */ jsxs8(
|
|
615
|
+
Link6,
|
|
616
|
+
{
|
|
617
|
+
href: `/articles/authors/${article.authorSlug}`,
|
|
618
|
+
className: "mb-4 flex items-center gap-2 text-sm text-muted-foreground hover:text-primary transition-colors",
|
|
619
|
+
onClick: () => emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
620
|
+
name: "author_clicked",
|
|
621
|
+
articleSlug: article.slug,
|
|
622
|
+
authorSlug: article.authorSlug
|
|
623
|
+
}),
|
|
624
|
+
children: [
|
|
625
|
+
article.authorAvatar ? /* @__PURE__ */ jsx8(
|
|
626
|
+
Image4,
|
|
627
|
+
{
|
|
628
|
+
src: article.authorAvatar,
|
|
629
|
+
alt: "",
|
|
630
|
+
width: 24,
|
|
631
|
+
height: 24,
|
|
632
|
+
className: "h-6 w-6 rounded-full object-cover"
|
|
633
|
+
}
|
|
634
|
+
) : /* @__PURE__ */ jsx8(
|
|
635
|
+
"span",
|
|
636
|
+
{
|
|
637
|
+
"aria-hidden": "true",
|
|
638
|
+
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-muted text-[10px] font-semibold text-muted-foreground",
|
|
639
|
+
children: getInitials(article.author)
|
|
640
|
+
}
|
|
641
|
+
),
|
|
642
|
+
/* @__PURE__ */ jsx8("span", { children: article.author })
|
|
643
|
+
]
|
|
644
|
+
}
|
|
645
|
+
),
|
|
646
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between text-sm text-muted-foreground border-t pt-4", children: [
|
|
647
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
|
|
648
|
+
article.date && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
649
|
+
/* @__PURE__ */ jsx8(Calendar2, { className: "h-3 w-3" }),
|
|
650
|
+
/* @__PURE__ */ jsx8("span", { children: article.date })
|
|
544
651
|
] }),
|
|
545
|
-
/* @__PURE__ */
|
|
546
|
-
/* @__PURE__ */
|
|
547
|
-
/* @__PURE__ */
|
|
652
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
653
|
+
/* @__PURE__ */ jsx8(Clock2, { className: "h-3 w-3" }),
|
|
654
|
+
/* @__PURE__ */ jsx8("span", { children: article.readTime })
|
|
548
655
|
] })
|
|
549
656
|
] }),
|
|
550
|
-
/* @__PURE__ */
|
|
551
|
-
|
|
657
|
+
/* @__PURE__ */ jsx8(
|
|
658
|
+
Link6,
|
|
552
659
|
{
|
|
553
660
|
href: `/articles/${article.slug}`,
|
|
554
661
|
className: "inline-flex items-center justify-center h-8 w-8 p-0 rounded-md hover:bg-accent transition-colors",
|
|
555
662
|
"aria-label": `Read ${article.title}`,
|
|
556
|
-
children: /* @__PURE__ */
|
|
663
|
+
children: /* @__PURE__ */ jsx8(ArrowRight2, { className: "h-4 w-4" })
|
|
557
664
|
}
|
|
558
665
|
)
|
|
559
666
|
] })
|
|
@@ -561,18 +668,114 @@ function ArticleCard({ article }) {
|
|
|
561
668
|
] });
|
|
562
669
|
}
|
|
563
670
|
|
|
671
|
+
// src/PaginationNav.tsx
|
|
672
|
+
import Link7 from "next/link";
|
|
673
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
674
|
+
|
|
675
|
+
// src/pagination.ts
|
|
676
|
+
function buildPageUrl(basePath, page) {
|
|
677
|
+
const base = basePath.replace(/\/$/, "");
|
|
678
|
+
return page > 1 ? `${base}/page/${page}` : base;
|
|
679
|
+
}
|
|
680
|
+
function buildPaginationLinks(basePath, page, totalPages) {
|
|
681
|
+
return {
|
|
682
|
+
canonicalUrl: buildPageUrl(basePath, page),
|
|
683
|
+
prevUrl: page > 1 ? buildPageUrl(basePath, page - 1) : null,
|
|
684
|
+
nextUrl: page < totalPages ? buildPageUrl(basePath, page + 1) : null
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// src/PaginationNav.tsx
|
|
689
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
690
|
+
function PaginationNav({ basePath, page, totalPages }) {
|
|
691
|
+
if (totalPages <= 1) return null;
|
|
692
|
+
const { prevUrl, nextUrl } = buildPaginationLinks(basePath, page, totalPages);
|
|
693
|
+
return /* @__PURE__ */ jsxs9(
|
|
694
|
+
"nav",
|
|
695
|
+
{
|
|
696
|
+
className: "mt-10 flex items-center justify-center gap-4",
|
|
697
|
+
"aria-label": "Article listing pagination",
|
|
698
|
+
children: [
|
|
699
|
+
prevUrl && /* @__PURE__ */ jsx9("link", { rel: "prev", href: prevUrl }),
|
|
700
|
+
nextUrl && /* @__PURE__ */ jsx9("link", { rel: "next", href: nextUrl }),
|
|
701
|
+
prevUrl ? /* @__PURE__ */ jsxs9(
|
|
702
|
+
Link7,
|
|
703
|
+
{
|
|
704
|
+
href: prevUrl,
|
|
705
|
+
className: "inline-flex items-center gap-1 px-4 py-2 border border-input bg-background hover:bg-accent rounded-md font-medium text-sm transition-colors",
|
|
706
|
+
children: [
|
|
707
|
+
/* @__PURE__ */ jsx9(ChevronLeft, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
708
|
+
"Previous"
|
|
709
|
+
]
|
|
710
|
+
}
|
|
711
|
+
) : /* @__PURE__ */ jsxs9(
|
|
712
|
+
"span",
|
|
713
|
+
{
|
|
714
|
+
"aria-hidden": "true",
|
|
715
|
+
className: "inline-flex items-center gap-1 px-4 py-2 rounded-md font-medium text-sm text-muted-foreground opacity-50",
|
|
716
|
+
children: [
|
|
717
|
+
/* @__PURE__ */ jsx9(ChevronLeft, { className: "h-4 w-4" }),
|
|
718
|
+
"Previous"
|
|
719
|
+
]
|
|
720
|
+
}
|
|
721
|
+
),
|
|
722
|
+
/* @__PURE__ */ jsxs9("span", { className: "text-sm text-muted-foreground", children: [
|
|
723
|
+
"Page ",
|
|
724
|
+
page,
|
|
725
|
+
" of ",
|
|
726
|
+
totalPages
|
|
727
|
+
] }),
|
|
728
|
+
nextUrl ? /* @__PURE__ */ jsxs9(
|
|
729
|
+
Link7,
|
|
730
|
+
{
|
|
731
|
+
href: nextUrl,
|
|
732
|
+
className: "inline-flex items-center gap-1 px-4 py-2 border border-input bg-background hover:bg-accent rounded-md font-medium text-sm transition-colors",
|
|
733
|
+
children: [
|
|
734
|
+
"Next",
|
|
735
|
+
/* @__PURE__ */ jsx9(ChevronRight, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
736
|
+
]
|
|
737
|
+
}
|
|
738
|
+
) : /* @__PURE__ */ jsxs9(
|
|
739
|
+
"span",
|
|
740
|
+
{
|
|
741
|
+
"aria-hidden": "true",
|
|
742
|
+
className: "inline-flex items-center gap-1 px-4 py-2 rounded-md font-medium text-sm text-muted-foreground opacity-50",
|
|
743
|
+
children: [
|
|
744
|
+
"Next",
|
|
745
|
+
/* @__PURE__ */ jsx9(ChevronRight, { className: "h-4 w-4" })
|
|
746
|
+
]
|
|
747
|
+
}
|
|
748
|
+
)
|
|
749
|
+
]
|
|
750
|
+
}
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
|
|
564
754
|
// src/LatestArticles.tsx
|
|
565
|
-
import { jsx as
|
|
566
|
-
function LatestArticles({ articles, pageSize }) {
|
|
755
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
756
|
+
function LatestArticles({ articles, pageSize, pagination }) {
|
|
567
757
|
const [visibleCount, setVisibleCount] = useState2(pageSize);
|
|
568
758
|
useEffect2(() => {
|
|
569
759
|
setVisibleCount(pageSize);
|
|
570
760
|
}, [articles, pageSize]);
|
|
761
|
+
if (pagination) {
|
|
762
|
+
return /* @__PURE__ */ jsxs10("div", { children: [
|
|
763
|
+
/* @__PURE__ */ jsx10("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-8", children: articles.map((article) => /* @__PURE__ */ jsx10(ArticleCard, { article }, article.slug)) }),
|
|
764
|
+
/* @__PURE__ */ jsx10(
|
|
765
|
+
PaginationNav,
|
|
766
|
+
{
|
|
767
|
+
basePath: pagination.basePath,
|
|
768
|
+
page: pagination.page,
|
|
769
|
+
totalPages: pagination.totalPages
|
|
770
|
+
}
|
|
771
|
+
)
|
|
772
|
+
] });
|
|
773
|
+
}
|
|
571
774
|
const visible = articles.slice(0, visibleCount);
|
|
572
775
|
const hasMore = visibleCount < articles.length;
|
|
573
|
-
return /* @__PURE__ */
|
|
574
|
-
/* @__PURE__ */
|
|
575
|
-
hasMore && /* @__PURE__ */
|
|
776
|
+
return /* @__PURE__ */ jsxs10("div", { children: [
|
|
777
|
+
/* @__PURE__ */ jsx10("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-8", children: visible.map((article) => /* @__PURE__ */ jsx10(ArticleCard, { article }, article.slug)) }),
|
|
778
|
+
hasMore && /* @__PURE__ */ jsx10("div", { className: "mt-10 text-center", children: /* @__PURE__ */ jsx10(
|
|
576
779
|
"button",
|
|
577
780
|
{
|
|
578
781
|
type: "button",
|
|
@@ -585,35 +788,36 @@ function LatestArticles({ articles, pageSize }) {
|
|
|
585
788
|
}
|
|
586
789
|
|
|
587
790
|
// src/LatestArticlesSection.tsx
|
|
588
|
-
import { jsx as
|
|
791
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
589
792
|
function DescriptionText({
|
|
590
793
|
searchQuery,
|
|
591
794
|
count
|
|
592
795
|
}) {
|
|
593
796
|
const pluralSuffix = count === 1 ? "" : "s";
|
|
594
797
|
const text = searchQuery ? `Found ${count} article${pluralSuffix} matching your search.` : "Stay informed with our latest insights on voter engagement, campaign strategies, and civic technology.";
|
|
595
|
-
return /* @__PURE__ */
|
|
798
|
+
return /* @__PURE__ */ jsx11("p", { className: "text-lg text-muted-foreground", children: text });
|
|
596
799
|
}
|
|
597
800
|
function LatestArticlesSection({
|
|
598
801
|
articles,
|
|
599
802
|
searchQuery,
|
|
600
803
|
onClearSearch,
|
|
601
|
-
pageSize = 6
|
|
804
|
+
pageSize = 6,
|
|
805
|
+
pagination
|
|
602
806
|
}) {
|
|
603
|
-
return /* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
605
|
-
/* @__PURE__ */
|
|
606
|
-
/* @__PURE__ */
|
|
807
|
+
return /* @__PURE__ */ jsx11("section", { id: "latest", className: "py-16 bg-muted/50", children: /* @__PURE__ */ jsxs11("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
|
|
808
|
+
/* @__PURE__ */ jsxs11("div", { className: "text-center mb-12", children: [
|
|
809
|
+
/* @__PURE__ */ jsx11("h2", { className: "text-3xl font-bold text-foreground mb-4", children: searchQuery ? "Search Results" : "Latest Articles" }),
|
|
810
|
+
/* @__PURE__ */ jsx11(DescriptionText, { searchQuery, count: articles.length })
|
|
607
811
|
] }),
|
|
608
|
-
articles.length === 0 && searchQuery ? /* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
610
|
-
/* @__PURE__ */
|
|
611
|
-
/* @__PURE__ */
|
|
812
|
+
articles.length === 0 && searchQuery ? /* @__PURE__ */ jsx11("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxs11("div", { className: "max-w-md mx-auto", children: [
|
|
813
|
+
/* @__PURE__ */ jsx11(Search2, { className: "h-12 w-12 text-muted-foreground mx-auto mb-4" }),
|
|
814
|
+
/* @__PURE__ */ jsx11("h3", { className: "text-lg font-semibold text-foreground mb-2", children: "No articles found" }),
|
|
815
|
+
/* @__PURE__ */ jsxs11("p", { className: "text-muted-foreground mb-4", children: [
|
|
612
816
|
`We couldn't find any articles matching "`,
|
|
613
817
|
searchQuery,
|
|
614
818
|
'". Try adjusting your search terms.'
|
|
615
819
|
] }),
|
|
616
|
-
/* @__PURE__ */
|
|
820
|
+
/* @__PURE__ */ jsx11(
|
|
617
821
|
"button",
|
|
618
822
|
{
|
|
619
823
|
type: "button",
|
|
@@ -622,7 +826,15 @@ function LatestArticlesSection({
|
|
|
622
826
|
children: "Clear search"
|
|
623
827
|
}
|
|
624
828
|
)
|
|
625
|
-
] }) }) : /* @__PURE__ */
|
|
829
|
+
] }) }) : /* @__PURE__ */ jsx11(
|
|
830
|
+
LatestArticles,
|
|
831
|
+
{
|
|
832
|
+
articles,
|
|
833
|
+
pageSize,
|
|
834
|
+
pagination: searchQuery ? void 0 : pagination
|
|
835
|
+
},
|
|
836
|
+
searchQuery
|
|
837
|
+
)
|
|
626
838
|
] }) });
|
|
627
839
|
}
|
|
628
840
|
|
|
@@ -648,12 +860,12 @@ function getBreadcrumbsConfig(config) {
|
|
|
648
860
|
|
|
649
861
|
// src/useArticles.ts
|
|
650
862
|
import { useState as useState3, useCallback, useEffect as useEffect3, useRef } from "react";
|
|
651
|
-
function useArticles() {
|
|
863
|
+
function useArticles(initialArticles, initialCategories) {
|
|
652
864
|
const [searchQuery, setSearchQuery] = useState3("");
|
|
653
865
|
const debounceRef = useRef(null);
|
|
654
|
-
const [articles, setArticles] = useState3([]);
|
|
655
|
-
const [categories, setCategories] = useState3([]);
|
|
656
|
-
const [loading, setLoading] = useState3(
|
|
866
|
+
const [articles, setArticles] = useState3(initialArticles != null ? initialArticles : []);
|
|
867
|
+
const [categories, setCategories] = useState3(initialCategories != null ? initialCategories : []);
|
|
868
|
+
const [loading, setLoading] = useState3(initialArticles === void 0);
|
|
657
869
|
const [error, setError] = useState3(null);
|
|
658
870
|
const fetchArticles = useCallback((query) => __async(this, null, function* () {
|
|
659
871
|
try {
|
|
@@ -691,7 +903,7 @@ function useArticles() {
|
|
|
691
903
|
}
|
|
692
904
|
}), []);
|
|
693
905
|
useEffect3(() => {
|
|
694
|
-
fetchArticles("");
|
|
906
|
+
if (initialArticles === void 0) fetchArticles("");
|
|
695
907
|
}, [fetchArticles]);
|
|
696
908
|
const handleSearch = useCallback(
|
|
697
909
|
(query) => {
|
|
@@ -715,7 +927,7 @@ function useArticles() {
|
|
|
715
927
|
}
|
|
716
928
|
|
|
717
929
|
// src/ArticlesPage.tsx
|
|
718
|
-
import { jsx as
|
|
930
|
+
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
719
931
|
function buildThemeVars(theme) {
|
|
720
932
|
if (!theme) return {};
|
|
721
933
|
const vars = {};
|
|
@@ -744,11 +956,12 @@ function renderSection(section, ctx, config) {
|
|
|
744
956
|
error,
|
|
745
957
|
handleSearch,
|
|
746
958
|
pageSize,
|
|
747
|
-
categoriesPageSize
|
|
959
|
+
categoriesPageSize,
|
|
960
|
+
pagination
|
|
748
961
|
} = ctx;
|
|
749
962
|
switch (section) {
|
|
750
963
|
case "hero":
|
|
751
|
-
return /* @__PURE__ */
|
|
964
|
+
return /* @__PURE__ */ jsx12(
|
|
752
965
|
ArticlesHero,
|
|
753
966
|
{
|
|
754
967
|
title: (_a = config.hero) == null ? void 0 : _a.title,
|
|
@@ -757,7 +970,7 @@ function renderSection(section, ctx, config) {
|
|
|
757
970
|
"hero"
|
|
758
971
|
);
|
|
759
972
|
case "search":
|
|
760
|
-
return /* @__PURE__ */
|
|
973
|
+
return /* @__PURE__ */ jsx12(
|
|
761
974
|
ArticleSearchBar,
|
|
762
975
|
{
|
|
763
976
|
value: searchQuery,
|
|
@@ -768,7 +981,7 @@ function renderSection(section, ctx, config) {
|
|
|
768
981
|
"search"
|
|
769
982
|
);
|
|
770
983
|
case "featured":
|
|
771
|
-
return articles.length > 0 && !searchQuery ? /* @__PURE__ */
|
|
984
|
+
return articles.length > 0 && !searchQuery ? /* @__PURE__ */ jsx12(
|
|
772
985
|
FeaturedArticle,
|
|
773
986
|
{
|
|
774
987
|
article: articles[0],
|
|
@@ -778,16 +991,16 @@ function renderSection(section, ctx, config) {
|
|
|
778
991
|
) : null;
|
|
779
992
|
case "latest":
|
|
780
993
|
if (loading && articles.length === 0) {
|
|
781
|
-
return /* @__PURE__ */
|
|
782
|
-
/* @__PURE__ */
|
|
783
|
-
/* @__PURE__ */
|
|
994
|
+
return /* @__PURE__ */ jsx12("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsx12("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center py-24", children: /* @__PURE__ */ jsxs12("div", { className: "text-center", children: [
|
|
995
|
+
/* @__PURE__ */ jsx12("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4" }),
|
|
996
|
+
/* @__PURE__ */ jsx12("p", { className: "text-muted-foreground", children: "Loading articles..." })
|
|
784
997
|
] }) }) }, "latest");
|
|
785
998
|
}
|
|
786
999
|
if (error) {
|
|
787
|
-
return /* @__PURE__ */
|
|
788
|
-
/* @__PURE__ */
|
|
789
|
-
/* @__PURE__ */
|
|
790
|
-
/* @__PURE__ */
|
|
1000
|
+
return /* @__PURE__ */ jsx12("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsx12("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center", children: /* @__PURE__ */ jsxs12("div", { className: "bg-red-50 border border-red-200 rounded-lg p-6 max-w-md text-center", children: [
|
|
1001
|
+
/* @__PURE__ */ jsx12("h3", { className: "text-lg font-semibold text-red-800 mb-2", children: "Error Loading Articles" }),
|
|
1002
|
+
/* @__PURE__ */ jsx12("p", { className: "text-red-600 mb-4", children: error }),
|
|
1003
|
+
/* @__PURE__ */ jsx12(
|
|
791
1004
|
"button",
|
|
792
1005
|
{
|
|
793
1006
|
type: "button",
|
|
@@ -798,18 +1011,19 @@ function renderSection(section, ctx, config) {
|
|
|
798
1011
|
)
|
|
799
1012
|
] }) }) }, "latest");
|
|
800
1013
|
}
|
|
801
|
-
return /* @__PURE__ */
|
|
1014
|
+
return /* @__PURE__ */ jsx12(
|
|
802
1015
|
LatestArticlesSection,
|
|
803
1016
|
{
|
|
804
1017
|
articles: displayedArticles,
|
|
805
1018
|
searchQuery,
|
|
806
1019
|
onClearSearch: () => handleSearch(""),
|
|
807
|
-
pageSize
|
|
1020
|
+
pageSize,
|
|
1021
|
+
pagination
|
|
808
1022
|
},
|
|
809
1023
|
"latest"
|
|
810
1024
|
);
|
|
811
1025
|
case "categories":
|
|
812
|
-
return searchQuery ? null : /* @__PURE__ */
|
|
1026
|
+
return searchQuery ? null : /* @__PURE__ */ jsx12(
|
|
813
1027
|
ArticleCategoryGrid,
|
|
814
1028
|
{
|
|
815
1029
|
categories,
|
|
@@ -822,26 +1036,48 @@ function renderSection(section, ctx, config) {
|
|
|
822
1036
|
return null;
|
|
823
1037
|
}
|
|
824
1038
|
}
|
|
825
|
-
function ArticlesPage({
|
|
1039
|
+
function ArticlesPage({
|
|
1040
|
+
config,
|
|
1041
|
+
initialArticles,
|
|
1042
|
+
initialCategories,
|
|
1043
|
+
page,
|
|
1044
|
+
totalPages,
|
|
1045
|
+
totalCount
|
|
1046
|
+
}) {
|
|
826
1047
|
var _a, _b, _c;
|
|
827
|
-
const state = useArticles();
|
|
1048
|
+
const state = useArticles(initialArticles, initialCategories);
|
|
828
1049
|
const layout = (_a = config.layout) != null ? _a : DEFAULT_LAYOUT;
|
|
829
1050
|
const pageSize = (_b = config.pageSize) != null ? _b : DEFAULT_PAGE_SIZE;
|
|
830
1051
|
const categoriesPageSize = (_c = config.categoriesPageSize) != null ? _c : DEFAULT_CATEGORIES_PAGE_SIZE;
|
|
831
1052
|
const themeVars = buildThemeVars(config.theme);
|
|
832
|
-
const
|
|
1053
|
+
const isPagesMode = config.listingPagination === "pages" && page !== void 0 && totalPages !== void 0;
|
|
1054
|
+
const currentPage = page != null ? page : 1;
|
|
1055
|
+
const effectiveLayout = isPagesMode && currentPage > 1 ? layout.filter((section) => section !== "featured") : layout;
|
|
1056
|
+
const hasFeatured = effectiveLayout.includes("featured");
|
|
833
1057
|
const articlesWithoutFeatured = hasFeatured ? state.articles.slice(1) : state.articles;
|
|
834
1058
|
const displayedArticles = state.searchQuery ? state.articles : articlesWithoutFeatured;
|
|
835
|
-
const
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
1059
|
+
const pagination = isPagesMode ? { page: currentPage, totalPages, basePath: "/articles" } : void 0;
|
|
1060
|
+
const ctx = __spreadProps(__spreadValues({}, state), {
|
|
1061
|
+
displayedArticles,
|
|
1062
|
+
pageSize,
|
|
1063
|
+
categoriesPageSize,
|
|
1064
|
+
pagination
|
|
1065
|
+
});
|
|
1066
|
+
const articleCount = totalCount != null ? totalCount : state.articles.length;
|
|
1067
|
+
return /* @__PURE__ */ jsxs12("div", { style: themeVars, children: [
|
|
1068
|
+
effectiveLayout.map((section) => renderSection(section, ctx, config)),
|
|
1069
|
+
state.articles.length > 0 && /* @__PURE__ */ jsx12(
|
|
839
1070
|
CollectionPageSchema,
|
|
840
1071
|
{
|
|
841
1072
|
title: `Articles | ${config.siteName}`,
|
|
842
|
-
description: `Browse all ${
|
|
1073
|
+
description: `Browse all ${articleCount} articles on ${config.siteName}.`,
|
|
843
1074
|
url: `${config.siteUrl}/articles`,
|
|
844
|
-
articleCount
|
|
1075
|
+
articleCount,
|
|
1076
|
+
items: displayedArticles.slice(0, pageSize).map((article, index) => ({
|
|
1077
|
+
position: index + 1,
|
|
1078
|
+
url: `${config.siteUrl}/articles/${article.slug}`,
|
|
1079
|
+
name: article.title
|
|
1080
|
+
}))
|
|
845
1081
|
}
|
|
846
1082
|
)
|
|
847
1083
|
] });
|
|
@@ -849,10 +1085,10 @@ function ArticlesPage({ config }) {
|
|
|
849
1085
|
|
|
850
1086
|
// src/ArticleDetailHero.tsx
|
|
851
1087
|
import { Fragment as Fragment3 } from "react";
|
|
852
|
-
import
|
|
853
|
-
import
|
|
1088
|
+
import Image5 from "next/image";
|
|
1089
|
+
import Link8 from "next/link";
|
|
854
1090
|
import { Calendar as Calendar3, Clock as Clock3, User as User2 } from "lucide-react";
|
|
855
|
-
import { jsx as
|
|
1091
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
856
1092
|
function toSlug(cat) {
|
|
857
1093
|
return cat.toLowerCase().replaceAll(/\s+/g, "-").replaceAll(/[^a-z0-9-]/g, "");
|
|
858
1094
|
}
|
|
@@ -865,7 +1101,7 @@ function ArticleDetailHero({
|
|
|
865
1101
|
}) {
|
|
866
1102
|
const showConfiguredAuthors = showAuthor && authors.length > 0;
|
|
867
1103
|
const showLegacyAuthor = showAuthor && authors.length === 0 && article.author.trim().length > 0;
|
|
868
|
-
return /* @__PURE__ */
|
|
1104
|
+
return /* @__PURE__ */ jsxs13(
|
|
869
1105
|
"section",
|
|
870
1106
|
{
|
|
871
1107
|
style: {
|
|
@@ -877,8 +1113,8 @@ function ArticleDetailHero({
|
|
|
877
1113
|
overflow: "hidden"
|
|
878
1114
|
},
|
|
879
1115
|
children: [
|
|
880
|
-
/* @__PURE__ */
|
|
881
|
-
|
|
1116
|
+
/* @__PURE__ */ jsx13(
|
|
1117
|
+
Image5,
|
|
882
1118
|
{
|
|
883
1119
|
src: article.featuredImage,
|
|
884
1120
|
alt: article.title,
|
|
@@ -889,7 +1125,7 @@ function ArticleDetailHero({
|
|
|
889
1125
|
priority: true
|
|
890
1126
|
}
|
|
891
1127
|
),
|
|
892
|
-
/* @__PURE__ */
|
|
1128
|
+
/* @__PURE__ */ jsx13(
|
|
893
1129
|
"div",
|
|
894
1130
|
{
|
|
895
1131
|
style: {
|
|
@@ -899,7 +1135,7 @@ function ArticleDetailHero({
|
|
|
899
1135
|
}
|
|
900
1136
|
}
|
|
901
1137
|
),
|
|
902
|
-
/* @__PURE__ */
|
|
1138
|
+
/* @__PURE__ */ jsxs13(
|
|
903
1139
|
"div",
|
|
904
1140
|
{
|
|
905
1141
|
style: {
|
|
@@ -913,7 +1149,7 @@ function ArticleDetailHero({
|
|
|
913
1149
|
width: "100%"
|
|
914
1150
|
},
|
|
915
1151
|
children: [
|
|
916
|
-
article.categories && article.categories.length > 0 && /* @__PURE__ */
|
|
1152
|
+
article.categories && article.categories.length > 0 && /* @__PURE__ */ jsx13(
|
|
917
1153
|
"div",
|
|
918
1154
|
{
|
|
919
1155
|
style: {
|
|
@@ -924,15 +1160,15 @@ function ArticleDetailHero({
|
|
|
924
1160
|
marginBottom: "1rem"
|
|
925
1161
|
},
|
|
926
1162
|
children: article.categories.slice(0, 4).map(
|
|
927
|
-
(cat) => categoryBasePath ? /* @__PURE__ */
|
|
928
|
-
|
|
1163
|
+
(cat) => categoryBasePath ? /* @__PURE__ */ jsx13(
|
|
1164
|
+
Link8,
|
|
929
1165
|
{
|
|
930
1166
|
href: `${categoryBasePath}/${toSlug(cat)}`,
|
|
931
1167
|
className: "inline-block bg-white/20 text-white text-sm font-medium px-3 py-1 rounded-full hover:bg-white/30 transition-colors",
|
|
932
1168
|
children: cat
|
|
933
1169
|
},
|
|
934
1170
|
cat
|
|
935
|
-
) : /* @__PURE__ */
|
|
1171
|
+
) : /* @__PURE__ */ jsx13(
|
|
936
1172
|
"span",
|
|
937
1173
|
{
|
|
938
1174
|
className: "inline-block bg-white/20 text-white text-sm font-medium px-3 py-1 rounded-full",
|
|
@@ -943,8 +1179,8 @@ function ArticleDetailHero({
|
|
|
943
1179
|
)
|
|
944
1180
|
}
|
|
945
1181
|
),
|
|
946
|
-
/* @__PURE__ */
|
|
947
|
-
/* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ jsx13("h1", { className: "text-4xl md:text-5xl font-bold mb-4", children: article.title }),
|
|
1183
|
+
/* @__PURE__ */ jsxs13(
|
|
948
1184
|
"div",
|
|
949
1185
|
{
|
|
950
1186
|
style: {
|
|
@@ -956,23 +1192,23 @@ function ArticleDetailHero({
|
|
|
956
1192
|
color: "rgba(255,255,255,0.8)"
|
|
957
1193
|
},
|
|
958
1194
|
children: [
|
|
959
|
-
showDate && article.date && /* @__PURE__ */
|
|
960
|
-
/* @__PURE__ */
|
|
961
|
-
/* @__PURE__ */
|
|
1195
|
+
showDate && article.date && /* @__PURE__ */ jsxs13("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1196
|
+
/* @__PURE__ */ jsx13(Calendar3, { className: "h-4 w-4" }),
|
|
1197
|
+
/* @__PURE__ */ jsx13("span", { children: article.date })
|
|
962
1198
|
] }),
|
|
963
|
-
/* @__PURE__ */
|
|
964
|
-
/* @__PURE__ */
|
|
965
|
-
/* @__PURE__ */
|
|
1199
|
+
/* @__PURE__ */ jsxs13("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1200
|
+
/* @__PURE__ */ jsx13(Clock3, { className: "h-4 w-4" }),
|
|
1201
|
+
/* @__PURE__ */ jsx13("span", { children: article.readTime })
|
|
966
1202
|
] }),
|
|
967
|
-
showConfiguredAuthors && /* @__PURE__ */
|
|
968
|
-
/* @__PURE__ */
|
|
969
|
-
/* @__PURE__ */
|
|
1203
|
+
showConfiguredAuthors && /* @__PURE__ */ jsxs13("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1204
|
+
/* @__PURE__ */ jsx13(User2, { className: "h-4 w-4" }),
|
|
1205
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
970
1206
|
"By",
|
|
971
1207
|
" ",
|
|
972
|
-
authors.map((author, index) => /* @__PURE__ */
|
|
1208
|
+
authors.map((author, index) => /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
973
1209
|
index > 0 && ", ",
|
|
974
|
-
/* @__PURE__ */
|
|
975
|
-
|
|
1210
|
+
/* @__PURE__ */ jsx13(
|
|
1211
|
+
Link8,
|
|
976
1212
|
{
|
|
977
1213
|
href: `/articles/authors/${author.slug}`,
|
|
978
1214
|
className: "font-medium text-white underline-offset-4 hover:underline",
|
|
@@ -982,15 +1218,26 @@ function ArticleDetailHero({
|
|
|
982
1218
|
] }, author.slug))
|
|
983
1219
|
] })
|
|
984
1220
|
] }),
|
|
985
|
-
showLegacyAuthor && /* @__PURE__ */
|
|
986
|
-
/* @__PURE__ */
|
|
987
|
-
/* @__PURE__ */
|
|
1221
|
+
showLegacyAuthor && /* @__PURE__ */ jsxs13("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1222
|
+
/* @__PURE__ */ jsx13(User2, { className: "h-4 w-4" }),
|
|
1223
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
988
1224
|
"By ",
|
|
989
1225
|
article.author
|
|
990
1226
|
] })
|
|
991
1227
|
] })
|
|
992
1228
|
]
|
|
993
1229
|
}
|
|
1230
|
+
),
|
|
1231
|
+
showConfiguredAuthors && authors.length === 1 && authors[0].promise && /* @__PURE__ */ jsx13(
|
|
1232
|
+
"p",
|
|
1233
|
+
{
|
|
1234
|
+
style: {
|
|
1235
|
+
marginTop: "0.75rem",
|
|
1236
|
+
fontSize: "0.9375rem",
|
|
1237
|
+
color: "rgba(255,255,255,0.85)"
|
|
1238
|
+
},
|
|
1239
|
+
children: authors[0].promise
|
|
1240
|
+
}
|
|
994
1241
|
)
|
|
995
1242
|
]
|
|
996
1243
|
}
|
|
@@ -1001,9 +1248,9 @@ function ArticleDetailHero({
|
|
|
1001
1248
|
}
|
|
1002
1249
|
|
|
1003
1250
|
// src/CategoryArticlesPage.tsx
|
|
1004
|
-
import
|
|
1005
|
-
import
|
|
1006
|
-
import { jsx as
|
|
1251
|
+
import Image6 from "next/image";
|
|
1252
|
+
import Link9 from "next/link";
|
|
1253
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1007
1254
|
function getCategoryDescription(config, slug, categoryName) {
|
|
1008
1255
|
var _a;
|
|
1009
1256
|
const raw = (_a = config.categoryDescriptions) == null ? void 0 : _a[slug];
|
|
@@ -1045,7 +1292,14 @@ function buildCategoryBreadcrumbEntry(entry, context) {
|
|
|
1045
1292
|
}
|
|
1046
1293
|
return [{ name: context.categoryName }];
|
|
1047
1294
|
}
|
|
1048
|
-
function CategoryArticlesPage({
|
|
1295
|
+
function CategoryArticlesPage({
|
|
1296
|
+
category,
|
|
1297
|
+
articles,
|
|
1298
|
+
config,
|
|
1299
|
+
page,
|
|
1300
|
+
totalPages,
|
|
1301
|
+
totalCount
|
|
1302
|
+
}) {
|
|
1049
1303
|
var _a;
|
|
1050
1304
|
if (articles.length === 0) return null;
|
|
1051
1305
|
const categoryName = articles[0].category;
|
|
@@ -1054,8 +1308,25 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1054
1308
|
const pageSize = (_a = config.pageSize) != null ? _a : DEFAULT_PAGE_SIZE;
|
|
1055
1309
|
const breadcrumbConfig = getBreadcrumbsConfig(config);
|
|
1056
1310
|
const breadcrumbItems = buildCategoryBreadcrumbItems(config, categoryName);
|
|
1057
|
-
|
|
1058
|
-
|
|
1311
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1312
|
+
const articleCount = totalCount != null ? totalCount : articles.length;
|
|
1313
|
+
const pagination = config.listingPagination === "pages" && page !== void 0 && totalPages !== void 0 ? { page, totalPages, basePath: `/articles/category/${category}` } : void 0;
|
|
1314
|
+
return /* @__PURE__ */ jsxs14("div", { children: [
|
|
1315
|
+
/* @__PURE__ */ jsx14(
|
|
1316
|
+
CollectionPageSchema,
|
|
1317
|
+
{
|
|
1318
|
+
title: `${categoryName} | ${config.siteName}`,
|
|
1319
|
+
description: description.short,
|
|
1320
|
+
url: `${siteUrl}/articles/category/${category}`,
|
|
1321
|
+
articleCount,
|
|
1322
|
+
items: articles.slice(0, pageSize).map((article, index) => ({
|
|
1323
|
+
position: index + 1,
|
|
1324
|
+
url: `${siteUrl}/articles/${article.slug}`,
|
|
1325
|
+
name: article.title
|
|
1326
|
+
}))
|
|
1327
|
+
}
|
|
1328
|
+
),
|
|
1329
|
+
breadcrumbsAreEnabled(config) && /* @__PURE__ */ jsx14(
|
|
1059
1330
|
Breadcrumb,
|
|
1060
1331
|
{
|
|
1061
1332
|
items: breadcrumbItems,
|
|
@@ -1063,7 +1334,7 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1063
1334
|
showSchema: breadcrumbConfig.showSchema !== false
|
|
1064
1335
|
}
|
|
1065
1336
|
),
|
|
1066
|
-
/* @__PURE__ */
|
|
1337
|
+
/* @__PURE__ */ jsxs14(
|
|
1067
1338
|
"section",
|
|
1068
1339
|
{
|
|
1069
1340
|
style: {
|
|
@@ -1075,8 +1346,8 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1075
1346
|
overflow: "hidden"
|
|
1076
1347
|
},
|
|
1077
1348
|
children: [
|
|
1078
|
-
/* @__PURE__ */
|
|
1079
|
-
|
|
1349
|
+
/* @__PURE__ */ jsx14(
|
|
1350
|
+
Image6,
|
|
1080
1351
|
{
|
|
1081
1352
|
src: heroImage,
|
|
1082
1353
|
alt: categoryName,
|
|
@@ -1086,8 +1357,8 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1086
1357
|
priority: true
|
|
1087
1358
|
}
|
|
1088
1359
|
),
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */
|
|
1360
|
+
/* @__PURE__ */ jsx14("div", { style: { position: "absolute", inset: 0, backgroundColor: "rgba(0,0,0,0.6)" } }),
|
|
1361
|
+
/* @__PURE__ */ jsxs14(
|
|
1091
1362
|
"div",
|
|
1092
1363
|
{
|
|
1093
1364
|
style: {
|
|
@@ -1098,10 +1369,10 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1098
1369
|
padding: "0 1rem"
|
|
1099
1370
|
},
|
|
1100
1371
|
children: [
|
|
1101
|
-
/* @__PURE__ */
|
|
1102
|
-
/* @__PURE__ */
|
|
1103
|
-
description.long && /* @__PURE__ */
|
|
1104
|
-
/* @__PURE__ */
|
|
1372
|
+
/* @__PURE__ */ jsx14("p", { className: "text-sm font-semibold uppercase tracking-widest mb-3 opacity-80", children: "Category" }),
|
|
1373
|
+
/* @__PURE__ */ jsx14("h1", { className: "text-4xl md:text-5xl font-bold mb-3", children: categoryName }),
|
|
1374
|
+
description.long && /* @__PURE__ */ jsx14("p", { className: "text-lg opacity-90 max-w-2xl mx-auto mt-2", children: description.long }),
|
|
1375
|
+
/* @__PURE__ */ jsxs14("p", { className: "text-lg opacity-70 mt-2", children: [
|
|
1105
1376
|
articles.length,
|
|
1106
1377
|
" article",
|
|
1107
1378
|
articles.length === 1 ? "" : "s"
|
|
@@ -1112,150 +1383,75 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1112
1383
|
]
|
|
1113
1384
|
}
|
|
1114
1385
|
),
|
|
1115
|
-
/* @__PURE__ */
|
|
1116
|
-
/* @__PURE__ */
|
|
1117
|
-
/* @__PURE__ */
|
|
1118
|
-
/* @__PURE__ */
|
|
1386
|
+
/* @__PURE__ */ jsx14("section", { className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsxs14("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
|
|
1387
|
+
/* @__PURE__ */ jsxs14("div", { className: "mb-8 flex items-center justify-between", children: [
|
|
1388
|
+
/* @__PURE__ */ jsx14(Link9, { href: "/articles", className: "text-sm text-primary hover:underline", children: "\u2190 All Articles" }),
|
|
1389
|
+
/* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: description.short })
|
|
1119
1390
|
] }),
|
|
1120
|
-
/* @__PURE__ */
|
|
1391
|
+
/* @__PURE__ */ jsx14(LatestArticles, { articles, pageSize, pagination })
|
|
1121
1392
|
] }) })
|
|
1122
1393
|
] });
|
|
1123
1394
|
}
|
|
1124
1395
|
|
|
1125
|
-
// src/
|
|
1126
|
-
import
|
|
1127
|
-
import { jsx as
|
|
1128
|
-
function
|
|
1129
|
-
var _a, _b;
|
|
1130
|
-
return __spreadProps(__spreadValues(__spreadValues({
|
|
1131
|
-
"@context": "https://schema.org",
|
|
1132
|
-
"@type": "Person",
|
|
1133
|
-
name: author.name,
|
|
1134
|
-
description: author.bio,
|
|
1135
|
-
url: (_a = author.url) != null ? _a : getAuthorUrl(author)
|
|
1136
|
-
}, getAuthorAvatar(author, config) && { image: getAuthorAvatar(author, config) }), getAuthorSameAs(author).length > 0 && { sameAs: getAuthorSameAs(author) }), {
|
|
1137
|
-
knowsAbout: config.siteName,
|
|
1138
|
-
mainEntityOfPage: (_b = author.url) != null ? _b : `${config.siteUrl.replace(/\/$/, "")}/articles/authors/${author.slug}`,
|
|
1139
|
-
interactionStatistic: {
|
|
1140
|
-
"@type": "InteractionCounter",
|
|
1141
|
-
interactionType: "https://schema.org/WriteAction",
|
|
1142
|
-
userInteractionCount: articleCount
|
|
1143
|
-
}
|
|
1144
|
-
});
|
|
1145
|
-
}
|
|
1146
|
-
function AuthorArticlesPage({ author, articles, config }) {
|
|
1396
|
+
// src/SeriesArticlesPage.tsx
|
|
1397
|
+
import Link10 from "next/link";
|
|
1398
|
+
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1399
|
+
function SeriesArticlesPage({ seriesSlug, articles, config }) {
|
|
1147
1400
|
var _a;
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1401
|
+
if (articles.length === 0) return null;
|
|
1402
|
+
const seriesName = (_a = articles[0].series) != null ? _a : seriesSlug;
|
|
1403
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1404
|
+
const seriesUrl = `${siteUrl}/articles/series/${seriesSlug}`;
|
|
1405
|
+
return /* @__PURE__ */ jsxs15("div", { children: [
|
|
1406
|
+
/* @__PURE__ */ jsx15(
|
|
1407
|
+
CollectionPageSchema,
|
|
1152
1408
|
{
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1409
|
+
title: `${seriesName} | ${config.siteName}`,
|
|
1410
|
+
description: `Follow the ${seriesName} series on ${config.siteName}.`,
|
|
1411
|
+
url: seriesUrl,
|
|
1412
|
+
articleCount: articles.length,
|
|
1413
|
+
items: articles.map((article, index) => ({
|
|
1414
|
+
position: index + 1,
|
|
1415
|
+
url: `${siteUrl}/articles/${article.slug}`,
|
|
1416
|
+
name: article.title
|
|
1417
|
+
}))
|
|
1157
1418
|
}
|
|
1158
1419
|
),
|
|
1159
|
-
/* @__PURE__ */
|
|
1160
|
-
/* @__PURE__ */
|
|
1161
|
-
/* @__PURE__ */
|
|
1162
|
-
/* @__PURE__ */
|
|
1163
|
-
|
|
1164
|
-
|
|
1420
|
+
/* @__PURE__ */ jsx15("section", { className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsxs15("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
|
|
1421
|
+
/* @__PURE__ */ jsxs15("div", { className: "mb-8 flex items-center justify-between", children: [
|
|
1422
|
+
/* @__PURE__ */ jsx15(Link10, { href: "/articles", className: "text-sm text-primary hover:underline", children: "\u2190 All Articles" }),
|
|
1423
|
+
/* @__PURE__ */ jsxs15("p", { className: "text-sm text-muted-foreground", children: [
|
|
1424
|
+
articles.length,
|
|
1425
|
+
" article",
|
|
1426
|
+
articles.length === 1 ? "" : "s",
|
|
1427
|
+
" in this series"
|
|
1165
1428
|
] })
|
|
1166
1429
|
] }),
|
|
1167
|
-
/* @__PURE__ */
|
|
1430
|
+
/* @__PURE__ */ jsx15("h1", { className: "text-3xl font-bold text-foreground mb-8", children: seriesName }),
|
|
1431
|
+
/* @__PURE__ */ jsx15(
|
|
1432
|
+
LatestArticles,
|
|
1433
|
+
{
|
|
1434
|
+
articles,
|
|
1435
|
+
pageSize: Math.max(articles.length, DEFAULT_PAGE_SIZE)
|
|
1436
|
+
}
|
|
1437
|
+
)
|
|
1168
1438
|
] }) })
|
|
1169
1439
|
] });
|
|
1170
1440
|
}
|
|
1171
1441
|
|
|
1172
|
-
// src/
|
|
1173
|
-
import
|
|
1174
|
-
import Link9 from "next/link";
|
|
1175
|
-
import {
|
|
1176
|
-
Facebook,
|
|
1177
|
-
Github,
|
|
1178
|
-
Globe,
|
|
1179
|
-
Instagram,
|
|
1180
|
-
Linkedin,
|
|
1181
|
-
Mail,
|
|
1182
|
-
MessageCircle,
|
|
1183
|
-
Twitter,
|
|
1184
|
-
Youtube
|
|
1185
|
-
} from "lucide-react";
|
|
1186
|
-
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1187
|
-
function getInitials(name) {
|
|
1188
|
-
return name.split(" ").filter(Boolean).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
|
|
1189
|
-
}
|
|
1190
|
-
function AuthorCard({
|
|
1191
|
-
author,
|
|
1192
|
-
linkToPage = true,
|
|
1193
|
-
showBio = false,
|
|
1194
|
-
showSocial = false
|
|
1195
|
-
}) {
|
|
1196
|
-
const avatar = getAuthorAvatar(author);
|
|
1197
|
-
const name = linkToPage ? /* @__PURE__ */ jsx14(Link9, { href: getAuthorUrl(author), className: "font-medium text-foreground hover:text-primary", children: author.name }) : /* @__PURE__ */ jsx14("span", { className: "font-medium text-foreground", children: author.name });
|
|
1198
|
-
return /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3 rounded-lg border border-border bg-card p-4 text-card-foreground", children: [
|
|
1199
|
-
avatar ? /* @__PURE__ */ jsx14(
|
|
1200
|
-
Image6,
|
|
1201
|
-
{
|
|
1202
|
-
src: avatar,
|
|
1203
|
-
alt: author.name,
|
|
1204
|
-
width: 48,
|
|
1205
|
-
height: 48,
|
|
1206
|
-
className: "h-12 w-12 rounded-full object-cover"
|
|
1207
|
-
}
|
|
1208
|
-
) : /* @__PURE__ */ jsx14("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) }),
|
|
1209
|
-
/* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
|
|
1210
|
-
name,
|
|
1211
|
-
showBio && author.bio && /* @__PURE__ */ jsx14("p", { className: "mt-1 line-clamp-2 text-sm text-muted-foreground", children: author.bio }),
|
|
1212
|
-
showSocial && /* @__PURE__ */ jsx14(AuthorSocialLinks, { author })
|
|
1213
|
-
] })
|
|
1214
|
-
] });
|
|
1215
|
-
}
|
|
1216
|
-
var SOCIAL_ICONS = {
|
|
1217
|
-
Website: Globe,
|
|
1218
|
-
Facebook,
|
|
1219
|
-
Twitter,
|
|
1220
|
-
X: Twitter,
|
|
1221
|
-
LinkedIn: Linkedin,
|
|
1222
|
-
Instagram,
|
|
1223
|
-
YouTube: Youtube,
|
|
1224
|
-
GitHub: Github,
|
|
1225
|
-
Newsletter: Mail
|
|
1226
|
-
};
|
|
1227
|
-
function getSocialIcon(label) {
|
|
1228
|
-
var _a;
|
|
1229
|
-
return (_a = SOCIAL_ICONS[label]) != null ? _a : MessageCircle;
|
|
1230
|
-
}
|
|
1231
|
-
function AuthorSocialLinks({ author }) {
|
|
1232
|
-
const links = getAuthorSocialLinks(author);
|
|
1233
|
-
if (links.length === 0) return null;
|
|
1234
|
-
return /* @__PURE__ */ jsx14("div", { className: "mt-3 flex items-center gap-2", children: links.map(({ href, label }) => {
|
|
1235
|
-
const Icon = getSocialIcon(label);
|
|
1236
|
-
return /* @__PURE__ */ jsx14(
|
|
1237
|
-
Link9,
|
|
1238
|
-
{
|
|
1239
|
-
href,
|
|
1240
|
-
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",
|
|
1241
|
-
"aria-label": `${author.name} on ${label}`,
|
|
1242
|
-
children: /* @__PURE__ */ jsx14(Icon, { className: "h-4 w-4" })
|
|
1243
|
-
},
|
|
1244
|
-
`${label}-${href}`
|
|
1245
|
-
);
|
|
1246
|
-
}) });
|
|
1247
|
-
}
|
|
1442
|
+
// src/AuthorArticlesPage.tsx
|
|
1443
|
+
import Link11 from "next/link";
|
|
1248
1444
|
|
|
1249
1445
|
// src/AuthorDetailHero.tsx
|
|
1250
1446
|
import Image7 from "next/image";
|
|
1251
|
-
import { jsx as
|
|
1447
|
+
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1252
1448
|
function getInitials2(name) {
|
|
1253
1449
|
return name.split(" ").filter(Boolean).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
|
|
1254
1450
|
}
|
|
1255
1451
|
function AuthorDetailHero({ author, articleCount }) {
|
|
1256
1452
|
const avatar = getAuthorAvatar(author);
|
|
1257
|
-
return /* @__PURE__ */
|
|
1258
|
-
avatar ? /* @__PURE__ */
|
|
1453
|
+
return /* @__PURE__ */ jsx16("section", { className: "bg-muted/40 py-16", children: /* @__PURE__ */ jsxs16("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: [
|
|
1454
|
+
avatar ? /* @__PURE__ */ jsx16(
|
|
1259
1455
|
Image7,
|
|
1260
1456
|
{
|
|
1261
1457
|
src: avatar,
|
|
@@ -1265,27 +1461,303 @@ function AuthorDetailHero({ author, articleCount }) {
|
|
|
1265
1461
|
className: "h-28 w-28 rounded-full object-cover",
|
|
1266
1462
|
priority: true
|
|
1267
1463
|
}
|
|
1268
|
-
) : /* @__PURE__ */
|
|
1269
|
-
/* @__PURE__ */
|
|
1270
|
-
/* @__PURE__ */
|
|
1271
|
-
/* @__PURE__ */
|
|
1272
|
-
/* @__PURE__ */
|
|
1273
|
-
typeof articleCount === "number" && /* @__PURE__ */
|
|
1464
|
+
) : /* @__PURE__ */ jsx16("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) }),
|
|
1465
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
1466
|
+
/* @__PURE__ */ jsx16("p", { className: "mb-3 text-sm font-semibold uppercase tracking-widest text-muted-foreground", children: "Author" }),
|
|
1467
|
+
/* @__PURE__ */ jsx16("h1", { className: "text-4xl font-bold text-foreground md:text-5xl", children: author.name }),
|
|
1468
|
+
/* @__PURE__ */ jsx16("p", { className: "mx-auto mt-4 max-w-2xl text-lg text-muted-foreground", children: author.bio }),
|
|
1469
|
+
typeof articleCount === "number" && /* @__PURE__ */ jsxs16("p", { className: "mt-3 text-sm text-muted-foreground", children: [
|
|
1274
1470
|
articleCount,
|
|
1275
1471
|
" article",
|
|
1276
1472
|
articleCount === 1 ? "" : "s"
|
|
1277
1473
|
] })
|
|
1278
1474
|
] }),
|
|
1279
|
-
/* @__PURE__ */
|
|
1475
|
+
/* @__PURE__ */ jsx16(AuthorSocialLinks, { author })
|
|
1280
1476
|
] }) });
|
|
1281
1477
|
}
|
|
1282
1478
|
|
|
1479
|
+
// src/eventTracking.tsx
|
|
1480
|
+
import { useEffect as useEffect4, useRef as useRef2 } from "react";
|
|
1481
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1482
|
+
var AVERAGE_WORDS_PER_MINUTE = 200;
|
|
1483
|
+
var DEFAULT_MEANINGFUL_READ_MS = 15e3;
|
|
1484
|
+
function ArticleViewTracker({ article, config }) {
|
|
1485
|
+
const firedMeaningfulRead = useRef2(false);
|
|
1486
|
+
useEffect4(() => {
|
|
1487
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
1488
|
+
name: "article_viewed",
|
|
1489
|
+
articleSlug: article.slug,
|
|
1490
|
+
category: article.category,
|
|
1491
|
+
seriesSlug: article.seriesSlug
|
|
1492
|
+
});
|
|
1493
|
+
const estimatedMs = article.wordCount ? article.wordCount / AVERAGE_WORDS_PER_MINUTE * 6e4 * 0.5 : DEFAULT_MEANINGFUL_READ_MS;
|
|
1494
|
+
const timer = setTimeout(() => {
|
|
1495
|
+
if (firedMeaningfulRead.current) return;
|
|
1496
|
+
firedMeaningfulRead.current = true;
|
|
1497
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, { name: "meaningful_read", articleSlug: article.slug });
|
|
1498
|
+
}, estimatedMs);
|
|
1499
|
+
return () => clearTimeout(timer);
|
|
1500
|
+
}, [article.slug]);
|
|
1501
|
+
return null;
|
|
1502
|
+
}
|
|
1503
|
+
function CtaViewTracker({ ctaId, articleSlug, config, children }) {
|
|
1504
|
+
const ref = useRef2(null);
|
|
1505
|
+
const fired = useRef2(false);
|
|
1506
|
+
useEffect4(() => {
|
|
1507
|
+
const node = ref.current;
|
|
1508
|
+
if (!node) return;
|
|
1509
|
+
function fire() {
|
|
1510
|
+
if (fired.current) return;
|
|
1511
|
+
fired.current = true;
|
|
1512
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, { name: "cta_viewed", ctaId, articleSlug });
|
|
1513
|
+
}
|
|
1514
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
1515
|
+
fire();
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
const observer = new IntersectionObserver(
|
|
1519
|
+
(entries) => {
|
|
1520
|
+
if (entries.some((entry) => entry.isIntersecting)) fire();
|
|
1521
|
+
},
|
|
1522
|
+
{ threshold: 0.5 }
|
|
1523
|
+
);
|
|
1524
|
+
observer.observe(node);
|
|
1525
|
+
return () => observer.disconnect();
|
|
1526
|
+
}, [ctaId, articleSlug]);
|
|
1527
|
+
return /* @__PURE__ */ jsx17("div", { ref, children });
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
// src/AuthorArticlesPage.tsx
|
|
1531
|
+
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1532
|
+
function getPersonSchema(author, config, articleCount) {
|
|
1533
|
+
var _a, _b;
|
|
1534
|
+
return __spreadProps(__spreadValues(__spreadValues({
|
|
1535
|
+
"@context": "https://schema.org",
|
|
1536
|
+
"@type": "Person",
|
|
1537
|
+
name: author.name,
|
|
1538
|
+
description: author.bio,
|
|
1539
|
+
url: (_a = author.url) != null ? _a : getAuthorUrl(author)
|
|
1540
|
+
}, getAuthorAvatar(author, config) && { image: getAuthorAvatar(author, config) }), getAuthorSameAs(author).length > 0 && { sameAs: getAuthorSameAs(author) }), {
|
|
1541
|
+
knowsAbout: config.siteName,
|
|
1542
|
+
mainEntityOfPage: (_b = author.url) != null ? _b : `${config.siteUrl.replace(/\/$/, "")}/articles/authors/${author.slug}`,
|
|
1543
|
+
interactionStatistic: {
|
|
1544
|
+
"@type": "InteractionCounter",
|
|
1545
|
+
interactionType: "https://schema.org/WriteAction",
|
|
1546
|
+
userInteractionCount: articleCount
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
function renderHeroSection(author, articleCount) {
|
|
1551
|
+
return /* @__PURE__ */ jsx18(AuthorDetailHero, { author, articleCount }, "hero");
|
|
1552
|
+
}
|
|
1553
|
+
function renderPromiseSection(author) {
|
|
1554
|
+
return author.promise ? /* @__PURE__ */ jsx18("section", { "aria-label": "Author promise", className: "bg-background py-12", children: /* @__PURE__ */ jsx18("div", { className: "mx-auto max-w-3xl px-4 text-center sm:px-6 lg:px-8", children: /* @__PURE__ */ jsx18("p", { className: "text-xl font-medium text-foreground md:text-2xl", children: author.promise }) }) }, "promise") : null;
|
|
1555
|
+
}
|
|
1556
|
+
function renderServesWhoSection(author) {
|
|
1557
|
+
return author.servesWho && author.servesWho.length > 0 ? /* @__PURE__ */ jsx18("section", { "aria-label": "Who this author serves", className: "bg-muted/40 py-12", children: /* @__PURE__ */ jsxs17("div", { className: "mx-auto max-w-3xl px-4 sm:px-6 lg:px-8", children: [
|
|
1558
|
+
/* @__PURE__ */ jsx18("h2", { className: "mb-4 text-center text-2xl font-bold text-foreground", children: "Who I help" }),
|
|
1559
|
+
/* @__PURE__ */ jsx18("ul", { className: "grid gap-3 sm:grid-cols-2", children: author.servesWho.map((who) => /* @__PURE__ */ jsx18(
|
|
1560
|
+
"li",
|
|
1561
|
+
{
|
|
1562
|
+
className: "rounded-lg border border-border bg-card px-4 py-3 text-sm text-card-foreground",
|
|
1563
|
+
children: who
|
|
1564
|
+
},
|
|
1565
|
+
who
|
|
1566
|
+
)) })
|
|
1567
|
+
] }) }, "servesWho") : null;
|
|
1568
|
+
}
|
|
1569
|
+
function renderOriginStorySection(author) {
|
|
1570
|
+
return author.originStory && author.originStory.length > 0 ? /* @__PURE__ */ jsx18("section", { "aria-label": "Author origin story", className: "bg-background py-12", children: /* @__PURE__ */ jsxs17("div", { className: "mx-auto max-w-3xl px-4 sm:px-6 lg:px-8", children: [
|
|
1571
|
+
/* @__PURE__ */ jsx18("h2", { className: "mb-6 text-2xl font-bold text-foreground", children: "My story" }),
|
|
1572
|
+
/* @__PURE__ */ jsx18("div", { className: "space-y-6", children: author.originStory.map((block, blockIndex) => {
|
|
1573
|
+
var _a;
|
|
1574
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
1575
|
+
block.heading && /* @__PURE__ */ jsx18("h3", { className: "mb-2 text-lg font-semibold text-foreground", children: block.heading }),
|
|
1576
|
+
block.paragraphs.map((paragraph, paragraphIndex) => {
|
|
1577
|
+
var _a2;
|
|
1578
|
+
return /* @__PURE__ */ jsx18(
|
|
1579
|
+
"p",
|
|
1580
|
+
{
|
|
1581
|
+
className: "mb-3 text-muted-foreground",
|
|
1582
|
+
children: paragraph
|
|
1583
|
+
},
|
|
1584
|
+
`${(_a2 = block.heading) != null ? _a2 : blockIndex}-${paragraph.slice(0, 40)}-${paragraphIndex}`
|
|
1585
|
+
);
|
|
1586
|
+
})
|
|
1587
|
+
] }, (_a = block.heading) != null ? _a : blockIndex);
|
|
1588
|
+
}) })
|
|
1589
|
+
] }) }, "originStory") : null;
|
|
1590
|
+
}
|
|
1591
|
+
function renderPrinciplesSection(author) {
|
|
1592
|
+
return author.principles && author.principles.length > 0 ? /* @__PURE__ */ jsx18("section", { "aria-label": "Author principles", className: "bg-muted/40 py-12", children: /* @__PURE__ */ jsxs17("div", { className: "mx-auto max-w-3xl px-4 sm:px-6 lg:px-8", children: [
|
|
1593
|
+
/* @__PURE__ */ jsx18("h2", { className: "mb-4 text-center text-2xl font-bold text-foreground", children: "What I believe" }),
|
|
1594
|
+
/* @__PURE__ */ jsx18("ul", { className: "space-y-3", children: author.principles.map((principle) => /* @__PURE__ */ jsx18(
|
|
1595
|
+
"li",
|
|
1596
|
+
{
|
|
1597
|
+
className: "rounded-lg border border-border bg-card px-4 py-3 text-sm text-card-foreground",
|
|
1598
|
+
children: principle
|
|
1599
|
+
},
|
|
1600
|
+
principle
|
|
1601
|
+
)) })
|
|
1602
|
+
] }) }, "principles") : null;
|
|
1603
|
+
}
|
|
1604
|
+
function renderProofSection(author) {
|
|
1605
|
+
return author.proof && author.proof.length > 0 ? /* @__PURE__ */ jsx18("section", { "aria-label": "Author proof", className: "bg-background py-12", children: /* @__PURE__ */ jsxs17("div", { className: "mx-auto max-w-4xl px-4 sm:px-6 lg:px-8", children: [
|
|
1606
|
+
/* @__PURE__ */ jsx18("h2", { className: "mb-6 text-center text-2xl font-bold text-foreground", children: "Proof" }),
|
|
1607
|
+
/* @__PURE__ */ jsx18("div", { className: "grid gap-4 sm:grid-cols-2", children: author.proof.map((item) => {
|
|
1608
|
+
var _a, _b, _c;
|
|
1609
|
+
return /* @__PURE__ */ jsxs17(
|
|
1610
|
+
"div",
|
|
1611
|
+
{
|
|
1612
|
+
className: "rounded-lg border border-border bg-card p-4 text-card-foreground",
|
|
1613
|
+
children: [
|
|
1614
|
+
/* @__PURE__ */ jsx18("p", { className: "font-medium", children: item.claim }),
|
|
1615
|
+
(item.source || item.url) && /* @__PURE__ */ jsx18("p", { className: "mt-1 text-sm text-muted-foreground", children: item.url ? /* @__PURE__ */ jsx18(Link11, { href: item.url, className: "hover:text-primary hover:underline", children: (_c = item.source) != null ? _c : item.url }) : item.source })
|
|
1616
|
+
]
|
|
1617
|
+
},
|
|
1618
|
+
`${item.claim}-${(_b = (_a = item.url) != null ? _a : item.source) != null ? _b : ""}`
|
|
1619
|
+
);
|
|
1620
|
+
}) })
|
|
1621
|
+
] }) }, "proof") : null;
|
|
1622
|
+
}
|
|
1623
|
+
function renderCtaSection(author, config) {
|
|
1624
|
+
return author.primaryCta ? /* @__PURE__ */ jsx18(CtaViewTracker, { ctaId: `author-cta:${author.slug}`, config, children: /* @__PURE__ */ jsx18("section", { "aria-label": "Author call to action", className: "bg-muted/40 py-12", children: /* @__PURE__ */ jsx18("div", { className: "mx-auto max-w-2xl px-4 text-center sm:px-6 lg:px-8", children: /* @__PURE__ */ jsx18(
|
|
1625
|
+
Link11,
|
|
1626
|
+
{
|
|
1627
|
+
href: author.primaryCta.href,
|
|
1628
|
+
onClick: () => emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
1629
|
+
name: "cta_clicked",
|
|
1630
|
+
ctaId: `author-cta:${author.slug}`
|
|
1631
|
+
}),
|
|
1632
|
+
className: "inline-flex items-center justify-center rounded-md bg-primary px-6 py-3 text-sm font-semibold text-primary-foreground hover:bg-primary/90",
|
|
1633
|
+
children: author.primaryCta.label
|
|
1634
|
+
}
|
|
1635
|
+
) }) }) }, "cta") : null;
|
|
1636
|
+
}
|
|
1637
|
+
function renderArticlesSection(author, articles, pageSize, pagination) {
|
|
1638
|
+
return /* @__PURE__ */ jsx18("section", { "aria-label": "Articles by this author", className: "bg-background py-16", children: /* @__PURE__ */ jsxs17("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8", children: [
|
|
1639
|
+
/* @__PURE__ */ jsxs17("div", { className: "mb-8 flex items-center justify-between gap-4", children: [
|
|
1640
|
+
/* @__PURE__ */ jsx18(Link11, { href: "/articles", className: "text-sm text-primary hover:underline", children: "All Articles" }),
|
|
1641
|
+
/* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
|
|
1642
|
+
"Articles by ",
|
|
1643
|
+
author.name
|
|
1644
|
+
] })
|
|
1645
|
+
] }),
|
|
1646
|
+
/* @__PURE__ */ jsx18(LatestArticles, { articles, pageSize, pagination })
|
|
1647
|
+
] }) }, "articles");
|
|
1648
|
+
}
|
|
1649
|
+
function renderAuthorSection(section, ctx) {
|
|
1650
|
+
const { author, articleCount, articles, pageSize, pagination, customSection, config } = ctx;
|
|
1651
|
+
switch (section) {
|
|
1652
|
+
case "hero":
|
|
1653
|
+
return renderHeroSection(author, articleCount);
|
|
1654
|
+
case "promise":
|
|
1655
|
+
return renderPromiseSection(author);
|
|
1656
|
+
case "servesWho":
|
|
1657
|
+
return renderServesWhoSection(author);
|
|
1658
|
+
case "originStory":
|
|
1659
|
+
return renderOriginStorySection(author);
|
|
1660
|
+
case "principles":
|
|
1661
|
+
return renderPrinciplesSection(author);
|
|
1662
|
+
case "proof":
|
|
1663
|
+
return renderProofSection(author);
|
|
1664
|
+
case "cta":
|
|
1665
|
+
return renderCtaSection(author, config);
|
|
1666
|
+
case "articles":
|
|
1667
|
+
return renderArticlesSection(author, articles, pageSize, pagination);
|
|
1668
|
+
case "custom":
|
|
1669
|
+
return customSection != null ? customSection : null;
|
|
1670
|
+
default:
|
|
1671
|
+
return null;
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
function AuthorArticlesPage({
|
|
1675
|
+
author,
|
|
1676
|
+
articles,
|
|
1677
|
+
config,
|
|
1678
|
+
page,
|
|
1679
|
+
totalPages,
|
|
1680
|
+
totalCount,
|
|
1681
|
+
sections,
|
|
1682
|
+
customSection
|
|
1683
|
+
}) {
|
|
1684
|
+
var _a, _b;
|
|
1685
|
+
const pageSize = (_a = config.pageSize) != null ? _a : DEFAULT_PAGE_SIZE;
|
|
1686
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1687
|
+
const articleCount = totalCount != null ? totalCount : articles.length;
|
|
1688
|
+
const pagination = config.listingPagination === "pages" && page !== void 0 && totalPages !== void 0 ? { page, totalPages, basePath: `/articles/authors/${author.slug}` } : void 0;
|
|
1689
|
+
const schemas = /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
1690
|
+
/* @__PURE__ */ jsx18(
|
|
1691
|
+
"script",
|
|
1692
|
+
{
|
|
1693
|
+
type: "application/ld+json",
|
|
1694
|
+
dangerouslySetInnerHTML: {
|
|
1695
|
+
__html: JSON.stringify(getPersonSchema(author, config, articleCount))
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
),
|
|
1699
|
+
/* @__PURE__ */ jsx18(
|
|
1700
|
+
CollectionPageSchema,
|
|
1701
|
+
{
|
|
1702
|
+
title: `${author.name} | ${config.siteName}`,
|
|
1703
|
+
description: `Articles by ${author.name} on ${config.siteName}.`,
|
|
1704
|
+
url: (_b = author.url) != null ? _b : `${siteUrl}/articles/authors/${author.slug}`,
|
|
1705
|
+
articleCount,
|
|
1706
|
+
items: articles.slice(0, pageSize).map((article, index) => ({
|
|
1707
|
+
position: index + 1,
|
|
1708
|
+
url: `${siteUrl}/articles/${article.slug}`,
|
|
1709
|
+
name: article.title
|
|
1710
|
+
}))
|
|
1711
|
+
}
|
|
1712
|
+
)
|
|
1713
|
+
] });
|
|
1714
|
+
if (!sections) {
|
|
1715
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
1716
|
+
schemas,
|
|
1717
|
+
/* @__PURE__ */ jsx18("section", { className: "bg-background py-16", children: /* @__PURE__ */ jsxs17("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8", children: [
|
|
1718
|
+
/* @__PURE__ */ jsxs17("div", { className: "mb-8 flex items-center justify-between gap-4", children: [
|
|
1719
|
+
/* @__PURE__ */ jsx18(Link11, { href: "/articles", className: "text-sm text-primary hover:underline", children: "All Articles" }),
|
|
1720
|
+
/* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
|
|
1721
|
+
"Articles by ",
|
|
1722
|
+
author.name
|
|
1723
|
+
] })
|
|
1724
|
+
] }),
|
|
1725
|
+
/* @__PURE__ */ jsx18(LatestArticles, { articles, pageSize, pagination })
|
|
1726
|
+
] }) })
|
|
1727
|
+
] });
|
|
1728
|
+
}
|
|
1729
|
+
const sectionCtx = {
|
|
1730
|
+
author,
|
|
1731
|
+
articleCount,
|
|
1732
|
+
articles,
|
|
1733
|
+
pageSize,
|
|
1734
|
+
pagination,
|
|
1735
|
+
customSection,
|
|
1736
|
+
config
|
|
1737
|
+
};
|
|
1738
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
1739
|
+
schemas,
|
|
1740
|
+
sections.map((section) => renderAuthorSection(section, sectionCtx))
|
|
1741
|
+
] });
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1283
1744
|
// src/ArticleSocialShare.tsx
|
|
1284
1745
|
import { useState as useState4 } from "react";
|
|
1285
1746
|
import { Share2, Copy, Check, Mail as Mail2, MessageCircle as MessageCircle2, Users, FileText } from "lucide-react";
|
|
1286
|
-
import { jsx as
|
|
1287
|
-
function ArticleSocialShare({
|
|
1747
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1748
|
+
function ArticleSocialShare({
|
|
1749
|
+
title,
|
|
1750
|
+
url,
|
|
1751
|
+
excerpt,
|
|
1752
|
+
shareMessage,
|
|
1753
|
+
config,
|
|
1754
|
+
articleSlug
|
|
1755
|
+
}) {
|
|
1288
1756
|
const [copied, setCopied] = useState4(false);
|
|
1757
|
+
function trackShare(channel) {
|
|
1758
|
+
if (!articleSlug) return;
|
|
1759
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, { name: "shared", articleSlug, channel });
|
|
1760
|
+
}
|
|
1289
1761
|
const encodedTitle = encodeURIComponent(title);
|
|
1290
1762
|
const encodedUrl = encodeURIComponent(url);
|
|
1291
1763
|
const encodedExcerpt = encodeURIComponent(excerpt || "");
|
|
@@ -1302,102 +1774,203 @@ function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
|
|
|
1302
1774
|
try {
|
|
1303
1775
|
yield navigator.clipboard.writeText(url);
|
|
1304
1776
|
setCopied(true);
|
|
1777
|
+
trackShare("copy-link");
|
|
1305
1778
|
setTimeout(() => setCopied(false), 2e3);
|
|
1306
1779
|
} catch (e) {
|
|
1307
1780
|
}
|
|
1308
1781
|
});
|
|
1309
|
-
const openShareWindow = (shareUrl) => {
|
|
1782
|
+
const openShareWindow = (shareUrl, channel) => {
|
|
1783
|
+
trackShare(channel);
|
|
1310
1784
|
globalThis.open(shareUrl, "_blank", "width=600,height=400,scrollbars=yes,resizable=yes");
|
|
1311
1785
|
};
|
|
1312
1786
|
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";
|
|
1313
|
-
return /* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
/* @__PURE__ */
|
|
1787
|
+
return /* @__PURE__ */ jsxs18("div", { className: "border-t border-border pt-8 mt-8", children: [
|
|
1788
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 mb-4", children: [
|
|
1789
|
+
/* @__PURE__ */ jsx19(Share2, { className: "h-5 w-5 text-muted-foreground" }),
|
|
1790
|
+
/* @__PURE__ */ jsx19("h3", { className: "text-lg font-semibold text-foreground", children: "Share this article" })
|
|
1317
1791
|
] }),
|
|
1318
|
-
/* @__PURE__ */
|
|
1319
|
-
/* @__PURE__ */
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
/* @__PURE__ */
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
/* @__PURE__ */
|
|
1344
|
-
|
|
1792
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap gap-2", children: [
|
|
1793
|
+
/* @__PURE__ */ jsxs18(
|
|
1794
|
+
"button",
|
|
1795
|
+
{
|
|
1796
|
+
type: "button",
|
|
1797
|
+
className: btnClass,
|
|
1798
|
+
onClick: () => openShareWindow(shareLinks.linkedin, "linkedin"),
|
|
1799
|
+
children: [
|
|
1800
|
+
/* @__PURE__ */ jsx19(Users, { className: "h-4 w-4" }),
|
|
1801
|
+
"LinkedIn"
|
|
1802
|
+
]
|
|
1803
|
+
}
|
|
1804
|
+
),
|
|
1805
|
+
/* @__PURE__ */ jsxs18(
|
|
1806
|
+
"button",
|
|
1807
|
+
{
|
|
1808
|
+
type: "button",
|
|
1809
|
+
className: btnClass,
|
|
1810
|
+
onClick: () => openShareWindow(shareLinks.facebook, "facebook"),
|
|
1811
|
+
children: [
|
|
1812
|
+
/* @__PURE__ */ jsx19("span", { className: "text-xs font-bold", children: "f" }),
|
|
1813
|
+
" Facebook"
|
|
1814
|
+
]
|
|
1815
|
+
}
|
|
1816
|
+
),
|
|
1817
|
+
/* @__PURE__ */ jsxs18(
|
|
1818
|
+
"button",
|
|
1819
|
+
{
|
|
1820
|
+
type: "button",
|
|
1821
|
+
className: btnClass,
|
|
1822
|
+
onClick: () => openShareWindow(shareLinks.twitter, "twitter"),
|
|
1823
|
+
children: [
|
|
1824
|
+
/* @__PURE__ */ jsx19(MessageCircle2, { className: "h-4 w-4" }),
|
|
1825
|
+
"Twitter"
|
|
1826
|
+
]
|
|
1827
|
+
}
|
|
1828
|
+
),
|
|
1829
|
+
/* @__PURE__ */ jsxs18(
|
|
1830
|
+
"button",
|
|
1831
|
+
{
|
|
1832
|
+
type: "button",
|
|
1833
|
+
className: btnClass,
|
|
1834
|
+
onClick: () => openShareWindow(shareLinks.reddit, "reddit"),
|
|
1835
|
+
children: [
|
|
1836
|
+
/* @__PURE__ */ jsx19(FileText, { className: "h-4 w-4" }),
|
|
1837
|
+
"Reddit"
|
|
1838
|
+
]
|
|
1839
|
+
}
|
|
1840
|
+
),
|
|
1841
|
+
/* @__PURE__ */ jsxs18(
|
|
1842
|
+
"button",
|
|
1843
|
+
{
|
|
1844
|
+
type: "button",
|
|
1845
|
+
className: btnClass,
|
|
1846
|
+
onClick: () => openShareWindow(shareLinks.whatsapp, "whatsapp"),
|
|
1847
|
+
children: [
|
|
1848
|
+
/* @__PURE__ */ jsx19(MessageCircle2, { className: "h-4 w-4" }),
|
|
1849
|
+
"WhatsApp"
|
|
1850
|
+
]
|
|
1851
|
+
}
|
|
1852
|
+
),
|
|
1853
|
+
/* @__PURE__ */ jsxs18(
|
|
1854
|
+
"button",
|
|
1855
|
+
{
|
|
1856
|
+
type: "button",
|
|
1857
|
+
className: btnClass,
|
|
1858
|
+
onClick: () => openShareWindow(shareLinks.telegram, "telegram"),
|
|
1859
|
+
children: [
|
|
1860
|
+
/* @__PURE__ */ jsx19(MessageCircle2, { className: "h-4 w-4" }),
|
|
1861
|
+
"Telegram"
|
|
1862
|
+
]
|
|
1863
|
+
}
|
|
1864
|
+
),
|
|
1865
|
+
/* @__PURE__ */ jsxs18("a", { className: btnClass, href: shareLinks.email, onClick: () => trackShare("email"), children: [
|
|
1866
|
+
/* @__PURE__ */ jsx19(Mail2, { className: "h-4 w-4" }),
|
|
1345
1867
|
"Email"
|
|
1346
1868
|
] }),
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
copied ? /* @__PURE__ */
|
|
1869
|
+
/* @__PURE__ */ jsxs18("button", { type: "button", className: btnClass, onClick: copyToClipboard, children: [
|
|
1870
|
+
copied ? /* @__PURE__ */ jsx19(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx19(Copy, { className: "h-4 w-4" }),
|
|
1349
1871
|
copied ? "Copied!" : "Copy Link"
|
|
1350
1872
|
] })
|
|
1351
1873
|
] }),
|
|
1352
|
-
shareMessage && /* @__PURE__ */
|
|
1874
|
+
shareMessage && /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground mt-3", children: shareMessage })
|
|
1353
1875
|
] });
|
|
1354
1876
|
}
|
|
1355
1877
|
|
|
1356
1878
|
// src/ArticleNavigation.tsx
|
|
1357
|
-
import
|
|
1358
|
-
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
1359
|
-
import { jsx as
|
|
1879
|
+
import Link12 from "next/link";
|
|
1880
|
+
import { ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight2 } from "lucide-react";
|
|
1881
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1360
1882
|
function truncateTitle(title, maxLength = 60) {
|
|
1361
1883
|
return title.length > maxLength ? `${title.substring(0, maxLength)}...` : title;
|
|
1362
1884
|
}
|
|
1363
|
-
function ArticleNavigation({
|
|
1885
|
+
function ArticleNavigation({
|
|
1886
|
+
previous,
|
|
1887
|
+
next,
|
|
1888
|
+
basePath,
|
|
1889
|
+
fromSlug,
|
|
1890
|
+
pathKey,
|
|
1891
|
+
config
|
|
1892
|
+
}) {
|
|
1364
1893
|
if (!previous && !next) return null;
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1894
|
+
function emitStep(toSlug2, direction) {
|
|
1895
|
+
if (!pathKey || !fromSlug) return;
|
|
1896
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
1897
|
+
name: "path_step_advanced",
|
|
1898
|
+
pathKey,
|
|
1899
|
+
fromSlug,
|
|
1900
|
+
toSlug: toSlug2,
|
|
1901
|
+
direction
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
return /* @__PURE__ */ jsx20("nav", { className: "mt-12 pt-8 border-t border-border", "aria-label": "Article navigation", children: /* @__PURE__ */ jsxs19("div", { className: "flex justify-between gap-4", children: [
|
|
1905
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: previous && /* @__PURE__ */ jsxs19(
|
|
1906
|
+
Link12,
|
|
1368
1907
|
{
|
|
1369
1908
|
href: `${basePath}/${previous.slug}`,
|
|
1909
|
+
onClick: () => emitStep(previous.slug, "previous"),
|
|
1370
1910
|
className: "group flex items-center gap-3 p-4 rounded-lg border border-border hover:border-primary/20 hover:bg-muted/50 transition-colors",
|
|
1371
1911
|
children: [
|
|
1372
|
-
/* @__PURE__ */
|
|
1373
|
-
/* @__PURE__ */
|
|
1374
|
-
/* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1912
|
+
/* @__PURE__ */ jsx20(ChevronLeft2, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" }),
|
|
1913
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0 flex-1", children: [
|
|
1914
|
+
/* @__PURE__ */ jsx20("div", { className: "text-sm text-muted-foreground mb-1", children: "Previous Article" }),
|
|
1915
|
+
/* @__PURE__ */ jsx20("div", { className: "font-medium text-foreground truncate", title: previous.title, children: truncateTitle(previous.title) })
|
|
1376
1916
|
] })
|
|
1377
1917
|
]
|
|
1378
1918
|
}
|
|
1379
1919
|
) }),
|
|
1380
|
-
/* @__PURE__ */
|
|
1381
|
-
|
|
1920
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: next && /* @__PURE__ */ jsxs19(
|
|
1921
|
+
Link12,
|
|
1382
1922
|
{
|
|
1383
1923
|
href: `${basePath}/${next.slug}`,
|
|
1924
|
+
onClick: () => emitStep(next.slug, "next"),
|
|
1384
1925
|
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",
|
|
1385
1926
|
children: [
|
|
1386
|
-
/* @__PURE__ */
|
|
1387
|
-
/* @__PURE__ */
|
|
1388
|
-
/* @__PURE__ */
|
|
1927
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0 flex-1 text-right", children: [
|
|
1928
|
+
/* @__PURE__ */ jsx20("div", { className: "text-sm text-muted-foreground mb-1", children: "Next Article" }),
|
|
1929
|
+
/* @__PURE__ */ jsx20("div", { className: "font-medium text-foreground truncate", title: next.title, children: truncateTitle(next.title) })
|
|
1389
1930
|
] }),
|
|
1390
|
-
/* @__PURE__ */
|
|
1931
|
+
/* @__PURE__ */ jsx20(ChevronRight2, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" })
|
|
1391
1932
|
]
|
|
1392
1933
|
}
|
|
1393
1934
|
) })
|
|
1394
1935
|
] }) });
|
|
1395
1936
|
}
|
|
1396
1937
|
|
|
1938
|
+
// src/RelatedArticlesSection.tsx
|
|
1939
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1940
|
+
function RelatedArticlesSection({
|
|
1941
|
+
articles,
|
|
1942
|
+
category,
|
|
1943
|
+
heading,
|
|
1944
|
+
config,
|
|
1945
|
+
fromSlug,
|
|
1946
|
+
source = "category"
|
|
1947
|
+
}) {
|
|
1948
|
+
if (articles.length === 0) return null;
|
|
1949
|
+
return /* @__PURE__ */ jsxs20("section", { className: "mt-12 pt-8 border-t border-border", "aria-label": "Related articles", children: [
|
|
1950
|
+
/* @__PURE__ */ jsx21("h2", { className: "text-xl font-semibold text-foreground mb-6", children: heading != null ? heading : `More in ${category}` }),
|
|
1951
|
+
/* @__PURE__ */ jsx21("div", { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: articles.map((article) => /* @__PURE__ */ jsx21(
|
|
1952
|
+
"div",
|
|
1953
|
+
{
|
|
1954
|
+
onClickCapture: () => {
|
|
1955
|
+
if (!fromSlug) return;
|
|
1956
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
1957
|
+
name: "related_article_clicked",
|
|
1958
|
+
fromSlug,
|
|
1959
|
+
toSlug: article.slug,
|
|
1960
|
+
source
|
|
1961
|
+
});
|
|
1962
|
+
},
|
|
1963
|
+
children: /* @__PURE__ */ jsx21(ArticleCard, { article, config })
|
|
1964
|
+
},
|
|
1965
|
+
article.slug
|
|
1966
|
+
)) })
|
|
1967
|
+
] });
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1397
1970
|
// src/ArticleBackLink.tsx
|
|
1398
|
-
import
|
|
1971
|
+
import Link13 from "next/link";
|
|
1399
1972
|
import { ArrowLeft } from "lucide-react";
|
|
1400
|
-
import { jsx as
|
|
1973
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1401
1974
|
function ArticleBackLink({
|
|
1402
1975
|
config,
|
|
1403
1976
|
href = "/articles",
|
|
@@ -1405,13 +1978,13 @@ function ArticleBackLink({
|
|
|
1405
1978
|
className
|
|
1406
1979
|
}) {
|
|
1407
1980
|
if (config.showBackToArticles === false) return null;
|
|
1408
|
-
return /* @__PURE__ */
|
|
1409
|
-
|
|
1981
|
+
return /* @__PURE__ */ jsxs21(
|
|
1982
|
+
Link13,
|
|
1410
1983
|
{
|
|
1411
1984
|
href,
|
|
1412
1985
|
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",
|
|
1413
1986
|
children: [
|
|
1414
|
-
/* @__PURE__ */
|
|
1987
|
+
/* @__PURE__ */ jsx22(ArrowLeft, { className: "h-4 w-4" }),
|
|
1415
1988
|
label
|
|
1416
1989
|
]
|
|
1417
1990
|
}
|
|
@@ -1419,17 +1992,17 @@ function ArticleBackLink({
|
|
|
1419
1992
|
}
|
|
1420
1993
|
|
|
1421
1994
|
// src/ArticleTOC.tsx
|
|
1422
|
-
import { jsx as
|
|
1995
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1423
1996
|
function ArticleTOC({ toc, className }) {
|
|
1424
1997
|
if (!toc.length) return null;
|
|
1425
|
-
return /* @__PURE__ */
|
|
1998
|
+
return /* @__PURE__ */ jsxs22(
|
|
1426
1999
|
"nav",
|
|
1427
2000
|
{
|
|
1428
2001
|
"aria-label": "Table of contents",
|
|
1429
2002
|
className: `mb-8 rounded-lg border border-border bg-muted/40 px-6 py-4 ${className != null ? className : ""}`,
|
|
1430
2003
|
children: [
|
|
1431
|
-
/* @__PURE__ */
|
|
1432
|
-
/* @__PURE__ */
|
|
2004
|
+
/* @__PURE__ */ jsx23("p", { className: "mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: "On this page" }),
|
|
2005
|
+
/* @__PURE__ */ jsx23("ul", { className: "space-y-1 text-sm", children: toc.map((item) => /* @__PURE__ */ jsx23("li", { style: { paddingLeft: `${Math.max(0, item.depth - 2) * 1}rem` }, children: /* @__PURE__ */ jsx23(
|
|
1433
2006
|
"a",
|
|
1434
2007
|
{
|
|
1435
2008
|
href: `#${item.id}`,
|
|
@@ -1443,35 +2016,35 @@ function ArticleTOC({ toc, className }) {
|
|
|
1443
2016
|
}
|
|
1444
2017
|
|
|
1445
2018
|
// src/ScrollToTop.tsx
|
|
1446
|
-
import { useEffect as
|
|
2019
|
+
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
1447
2020
|
import { ArrowUp } from "lucide-react";
|
|
1448
|
-
import { jsx as
|
|
2021
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1449
2022
|
function ScrollToTop() {
|
|
1450
2023
|
const [visible, setVisible] = useState5(false);
|
|
1451
|
-
|
|
2024
|
+
useEffect5(() => {
|
|
1452
2025
|
const onScroll = () => setVisible(globalThis.scrollY > 300);
|
|
1453
2026
|
globalThis.addEventListener("scroll", onScroll, { passive: true });
|
|
1454
2027
|
return () => globalThis.removeEventListener("scroll", onScroll);
|
|
1455
2028
|
}, []);
|
|
1456
2029
|
if (!visible) return null;
|
|
1457
|
-
return /* @__PURE__ */
|
|
2030
|
+
return /* @__PURE__ */ jsx24(
|
|
1458
2031
|
"button",
|
|
1459
2032
|
{
|
|
1460
2033
|
"aria-label": "Scroll to top",
|
|
1461
2034
|
onClick: () => globalThis.scrollTo({ top: 0, behavior: "smooth" }),
|
|
1462
2035
|
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",
|
|
1463
|
-
children: /* @__PURE__ */
|
|
2036
|
+
children: /* @__PURE__ */ jsx24(ArrowUp, { className: "h-5 w-5" })
|
|
1464
2037
|
}
|
|
1465
2038
|
);
|
|
1466
2039
|
}
|
|
1467
2040
|
|
|
1468
2041
|
// src/CommentsSection.tsx
|
|
1469
2042
|
import { useSession, signIn } from "next-auth/react";
|
|
1470
|
-
import { useCallback as useCallback2, useEffect as
|
|
2043
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useState as useState8 } from "react";
|
|
1471
2044
|
|
|
1472
2045
|
// src/CommentForm.tsx
|
|
1473
2046
|
import { useState as useState6 } from "react";
|
|
1474
|
-
import { jsx as
|
|
2047
|
+
import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1475
2048
|
var MAX_LENGTH = 2e3;
|
|
1476
2049
|
var WARN_THRESHOLD = 1800;
|
|
1477
2050
|
function submitLabel(submitting, parentId) {
|
|
@@ -1510,8 +2083,8 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1510
2083
|
}
|
|
1511
2084
|
});
|
|
1512
2085
|
}
|
|
1513
|
-
return /* @__PURE__ */
|
|
1514
|
-
/* @__PURE__ */
|
|
2086
|
+
return /* @__PURE__ */ jsxs23("form", { onSubmit: handleSubmit, className: "space-y-2", children: [
|
|
2087
|
+
/* @__PURE__ */ jsx25(
|
|
1515
2088
|
"textarea",
|
|
1516
2089
|
{
|
|
1517
2090
|
value: body,
|
|
@@ -1524,13 +2097,13 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1524
2097
|
"aria-label": parentId ? "Reply text" : "Comment text"
|
|
1525
2098
|
}
|
|
1526
2099
|
),
|
|
1527
|
-
remaining <= MAX_LENGTH - WARN_THRESHOLD && /* @__PURE__ */
|
|
2100
|
+
remaining <= MAX_LENGTH - WARN_THRESHOLD && /* @__PURE__ */ jsxs23("p", { className: `text-xs ${remaining < 0 ? "text-destructive" : "text-muted-foreground"}`, children: [
|
|
1528
2101
|
remaining,
|
|
1529
2102
|
" characters remaining"
|
|
1530
2103
|
] }),
|
|
1531
|
-
error && /* @__PURE__ */
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
2104
|
+
error && /* @__PURE__ */ jsx25("p", { className: "text-xs text-destructive", children: error }),
|
|
2105
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex gap-2", children: [
|
|
2106
|
+
/* @__PURE__ */ jsx25(
|
|
1534
2107
|
"button",
|
|
1535
2108
|
{
|
|
1536
2109
|
type: "submit",
|
|
@@ -1539,7 +2112,7 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1539
2112
|
children: submitLabel(submitting, parentId)
|
|
1540
2113
|
}
|
|
1541
2114
|
),
|
|
1542
|
-
onCancel && /* @__PURE__ */
|
|
2115
|
+
onCancel && /* @__PURE__ */ jsx25(
|
|
1543
2116
|
"button",
|
|
1544
2117
|
{
|
|
1545
2118
|
type: "button",
|
|
@@ -1554,7 +2127,7 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1554
2127
|
|
|
1555
2128
|
// src/CommentItem.tsx
|
|
1556
2129
|
import { useState as useState7 } from "react";
|
|
1557
|
-
import { Fragment as
|
|
2130
|
+
import { Fragment as Fragment5, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1558
2131
|
function relativeTime(iso) {
|
|
1559
2132
|
const diff = Date.now() - new Date(iso).getTime();
|
|
1560
2133
|
const minutes = Math.floor(diff / 6e4);
|
|
@@ -1592,15 +2165,15 @@ function CommentItem({
|
|
|
1592
2165
|
}
|
|
1593
2166
|
});
|
|
1594
2167
|
}
|
|
1595
|
-
return /* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
/* @__PURE__ */
|
|
1598
|
-
/* @__PURE__ */
|
|
1599
|
-
/* @__PURE__ */
|
|
2168
|
+
return /* @__PURE__ */ jsxs24("div", { className: `${isReply ? "ml-8 border-l-2 border-border pl-4" : ""}`, children: [
|
|
2169
|
+
/* @__PURE__ */ jsx26("div", { className: "rounded-lg bg-muted/40 p-3 space-y-1", children: comment.isDeleted ? /* @__PURE__ */ jsx26("p", { className: "text-sm italic text-muted-foreground", children: "Comment removed" }) : /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
2170
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2171
|
+
/* @__PURE__ */ jsx26("span", { className: "text-sm font-medium text-foreground", children: comment.authorName }),
|
|
2172
|
+
/* @__PURE__ */ jsx26("span", { className: "text-xs text-muted-foreground", children: relativeTime(comment.createdAt) })
|
|
1600
2173
|
] }),
|
|
1601
|
-
/* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
canReply && /* @__PURE__ */
|
|
2174
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm text-foreground whitespace-pre-wrap break-words", children: comment.body }),
|
|
2175
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex gap-3 pt-1", children: [
|
|
2176
|
+
canReply && /* @__PURE__ */ jsx26(
|
|
1604
2177
|
"button",
|
|
1605
2178
|
{
|
|
1606
2179
|
onClick: () => setShowReplyForm((v) => !v),
|
|
@@ -1608,7 +2181,7 @@ function CommentItem({
|
|
|
1608
2181
|
children: showReplyForm ? "Cancel" : "Reply"
|
|
1609
2182
|
}
|
|
1610
2183
|
),
|
|
1611
|
-
canDelete && /* @__PURE__ */
|
|
2184
|
+
canDelete && /* @__PURE__ */ jsx26(
|
|
1612
2185
|
"button",
|
|
1613
2186
|
{
|
|
1614
2187
|
onClick: handleDelete,
|
|
@@ -1619,7 +2192,7 @@ function CommentItem({
|
|
|
1619
2192
|
)
|
|
1620
2193
|
] })
|
|
1621
2194
|
] }) }),
|
|
1622
|
-
showReplyForm && /* @__PURE__ */
|
|
2195
|
+
showReplyForm && /* @__PURE__ */ jsx26("div", { className: "mt-2 ml-2", children: /* @__PURE__ */ jsx26(
|
|
1623
2196
|
CommentForm,
|
|
1624
2197
|
{
|
|
1625
2198
|
articleSlug,
|
|
@@ -1631,7 +2204,7 @@ function CommentItem({
|
|
|
1631
2204
|
onCancel: () => setShowReplyForm(false)
|
|
1632
2205
|
}
|
|
1633
2206
|
) }),
|
|
1634
|
-
replies.length > 0 && /* @__PURE__ */
|
|
2207
|
+
replies.length > 0 && /* @__PURE__ */ jsx26("div", { className: "mt-2 space-y-2", children: replies.map((reply) => /* @__PURE__ */ jsx26(
|
|
1635
2208
|
CommentItem,
|
|
1636
2209
|
{
|
|
1637
2210
|
comment: __spreadProps(__spreadValues({}, reply), { replies: [] }),
|
|
@@ -1646,7 +2219,7 @@ function CommentItem({
|
|
|
1646
2219
|
}
|
|
1647
2220
|
|
|
1648
2221
|
// src/CommentThread.tsx
|
|
1649
|
-
import { jsx as
|
|
2222
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
1650
2223
|
function CommentThread({
|
|
1651
2224
|
comments,
|
|
1652
2225
|
articleSlug,
|
|
@@ -1654,9 +2227,9 @@ function CommentThread({
|
|
|
1654
2227
|
onRefresh
|
|
1655
2228
|
}) {
|
|
1656
2229
|
if (comments.length === 0) {
|
|
1657
|
-
return /* @__PURE__ */
|
|
2230
|
+
return /* @__PURE__ */ jsx27("p", { className: "text-sm text-muted-foreground text-center py-6", children: "No comments yet. Be the first to share your thoughts." });
|
|
1658
2231
|
}
|
|
1659
|
-
return /* @__PURE__ */
|
|
2232
|
+
return /* @__PURE__ */ jsx27("div", { className: "space-y-4", children: comments.map((comment) => /* @__PURE__ */ jsx27(
|
|
1660
2233
|
CommentItem,
|
|
1661
2234
|
{
|
|
1662
2235
|
comment,
|
|
@@ -1669,7 +2242,7 @@ function CommentThread({
|
|
|
1669
2242
|
}
|
|
1670
2243
|
|
|
1671
2244
|
// src/CommentsSection.tsx
|
|
1672
|
-
import { jsx as
|
|
2245
|
+
import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1673
2246
|
function CommentsSection({ articleSlug, config }) {
|
|
1674
2247
|
var _a, _b, _c, _d, _e, _f;
|
|
1675
2248
|
const { data: session, status } = useSession();
|
|
@@ -1693,7 +2266,7 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1693
2266
|
setLoading(false);
|
|
1694
2267
|
}
|
|
1695
2268
|
}), [articleSlug]);
|
|
1696
|
-
|
|
2269
|
+
useEffect6(() => {
|
|
1697
2270
|
if (enabled) {
|
|
1698
2271
|
fetchComments().catch(() => void 0);
|
|
1699
2272
|
}
|
|
@@ -1701,10 +2274,10 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1701
2274
|
if (!enabled) return null;
|
|
1702
2275
|
const count = comments.length;
|
|
1703
2276
|
const label = count === 1 ? "1 comment" : `${count} comments`;
|
|
1704
|
-
return /* @__PURE__ */
|
|
1705
|
-
/* @__PURE__ */
|
|
1706
|
-
status === "authenticated" ? /* @__PURE__ */
|
|
1707
|
-
/* @__PURE__ */
|
|
2277
|
+
return /* @__PURE__ */ jsxs25("section", { "aria-label": "Comments", className: "mt-12 pt-8 border-t border-border space-y-6", children: [
|
|
2278
|
+
/* @__PURE__ */ jsx28("h2", { className: "text-xl font-semibold text-foreground", children: loading ? "Comments" : label }),
|
|
2279
|
+
status === "authenticated" ? /* @__PURE__ */ jsx28(CommentForm, { articleSlug, onSuccess: fetchComments }) : /* @__PURE__ */ jsxs25("p", { className: "text-sm text-muted-foreground", children: [
|
|
2280
|
+
/* @__PURE__ */ jsx28(
|
|
1708
2281
|
"button",
|
|
1709
2282
|
{
|
|
1710
2283
|
onClick: () => signIn(),
|
|
@@ -1715,8 +2288,8 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1715
2288
|
" ",
|
|
1716
2289
|
"to join the discussion."
|
|
1717
2290
|
] }),
|
|
1718
|
-
fetchError && /* @__PURE__ */
|
|
1719
|
-
loading ? /* @__PURE__ */
|
|
2291
|
+
fetchError && /* @__PURE__ */ jsx28("p", { className: "text-sm text-destructive", children: fetchError }),
|
|
2292
|
+
loading ? /* @__PURE__ */ jsx28("p", { className: "text-sm text-muted-foreground", children: "Loading comments\u2026" }) : /* @__PURE__ */ jsx28(
|
|
1720
2293
|
CommentThread,
|
|
1721
2294
|
{
|
|
1722
2295
|
comments,
|
|
@@ -1734,10 +2307,10 @@ export {
|
|
|
1734
2307
|
ArticleDetailHero,
|
|
1735
2308
|
ArticleNavigation,
|
|
1736
2309
|
ArticleSEO,
|
|
1737
|
-
ArticleSchema,
|
|
1738
2310
|
ArticleSearchBar,
|
|
1739
2311
|
ArticleSocialShare,
|
|
1740
2312
|
ArticleTOC,
|
|
2313
|
+
ArticleViewTracker,
|
|
1741
2314
|
ArticlesHero,
|
|
1742
2315
|
ArticlesPage,
|
|
1743
2316
|
AuthorArticlesPage,
|
|
@@ -1752,6 +2325,7 @@ export {
|
|
|
1752
2325
|
CommentItem,
|
|
1753
2326
|
CommentThread,
|
|
1754
2327
|
CommentsSection,
|
|
2328
|
+
CtaViewTracker,
|
|
1755
2329
|
DEFAULT_CATEGORIES_PAGE_SIZE,
|
|
1756
2330
|
DEFAULT_LAYOUT,
|
|
1757
2331
|
DEFAULT_PAGE_SIZE,
|
|
@@ -1759,7 +2333,10 @@ export {
|
|
|
1759
2333
|
FeaturedArticle,
|
|
1760
2334
|
LatestArticles,
|
|
1761
2335
|
LatestArticlesSection,
|
|
2336
|
+
PaginationNav,
|
|
2337
|
+
RelatedArticlesSection,
|
|
1762
2338
|
ScrollToTop,
|
|
2339
|
+
SeriesArticlesPage,
|
|
1763
2340
|
breadcrumbsAreEnabled,
|
|
1764
2341
|
getBreadcrumbsConfig,
|
|
1765
2342
|
useArticles
|