@fullstackdatasolutions/articles 0.12.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 +24 -0
- package/README.md +550 -3
- package/dist/index.cjs +960 -383
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +372 -20
- package/dist/index.d.ts +372 -20
- package/dist/index.js +944 -371
- 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 +55 -5
- 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 +131 -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__/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/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
|
|
|
@@ -715,7 +927,7 @@ function useArticles(initialArticles, initialCategories) {
|
|
|
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,
|
|
@@ -825,7 +1039,10 @@ function renderSection(section, ctx, config) {
|
|
|
825
1039
|
function ArticlesPage({
|
|
826
1040
|
config,
|
|
827
1041
|
initialArticles,
|
|
828
|
-
initialCategories
|
|
1042
|
+
initialCategories,
|
|
1043
|
+
page,
|
|
1044
|
+
totalPages,
|
|
1045
|
+
totalCount
|
|
829
1046
|
}) {
|
|
830
1047
|
var _a, _b, _c;
|
|
831
1048
|
const state = useArticles(initialArticles, initialCategories);
|
|
@@ -833,19 +1050,34 @@ function ArticlesPage({
|
|
|
833
1050
|
const pageSize = (_b = config.pageSize) != null ? _b : DEFAULT_PAGE_SIZE;
|
|
834
1051
|
const categoriesPageSize = (_c = config.categoriesPageSize) != null ? _c : DEFAULT_CATEGORIES_PAGE_SIZE;
|
|
835
1052
|
const themeVars = buildThemeVars(config.theme);
|
|
836
|
-
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");
|
|
837
1057
|
const articlesWithoutFeatured = hasFeatured ? state.articles.slice(1) : state.articles;
|
|
838
1058
|
const displayedArticles = state.searchQuery ? state.articles : articlesWithoutFeatured;
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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(
|
|
843
1070
|
CollectionPageSchema,
|
|
844
1071
|
{
|
|
845
1072
|
title: `Articles | ${config.siteName}`,
|
|
846
|
-
description: `Browse all ${
|
|
1073
|
+
description: `Browse all ${articleCount} articles on ${config.siteName}.`,
|
|
847
1074
|
url: `${config.siteUrl}/articles`,
|
|
848
|
-
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
|
+
}))
|
|
849
1081
|
}
|
|
850
1082
|
)
|
|
851
1083
|
] });
|
|
@@ -853,10 +1085,10 @@ function ArticlesPage({
|
|
|
853
1085
|
|
|
854
1086
|
// src/ArticleDetailHero.tsx
|
|
855
1087
|
import { Fragment as Fragment3 } from "react";
|
|
856
|
-
import
|
|
857
|
-
import
|
|
1088
|
+
import Image5 from "next/image";
|
|
1089
|
+
import Link8 from "next/link";
|
|
858
1090
|
import { Calendar as Calendar3, Clock as Clock3, User as User2 } from "lucide-react";
|
|
859
|
-
import { jsx as
|
|
1091
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
860
1092
|
function toSlug(cat) {
|
|
861
1093
|
return cat.toLowerCase().replaceAll(/\s+/g, "-").replaceAll(/[^a-z0-9-]/g, "");
|
|
862
1094
|
}
|
|
@@ -869,7 +1101,7 @@ function ArticleDetailHero({
|
|
|
869
1101
|
}) {
|
|
870
1102
|
const showConfiguredAuthors = showAuthor && authors.length > 0;
|
|
871
1103
|
const showLegacyAuthor = showAuthor && authors.length === 0 && article.author.trim().length > 0;
|
|
872
|
-
return /* @__PURE__ */
|
|
1104
|
+
return /* @__PURE__ */ jsxs13(
|
|
873
1105
|
"section",
|
|
874
1106
|
{
|
|
875
1107
|
style: {
|
|
@@ -881,8 +1113,8 @@ function ArticleDetailHero({
|
|
|
881
1113
|
overflow: "hidden"
|
|
882
1114
|
},
|
|
883
1115
|
children: [
|
|
884
|
-
/* @__PURE__ */
|
|
885
|
-
|
|
1116
|
+
/* @__PURE__ */ jsx13(
|
|
1117
|
+
Image5,
|
|
886
1118
|
{
|
|
887
1119
|
src: article.featuredImage,
|
|
888
1120
|
alt: article.title,
|
|
@@ -893,7 +1125,7 @@ function ArticleDetailHero({
|
|
|
893
1125
|
priority: true
|
|
894
1126
|
}
|
|
895
1127
|
),
|
|
896
|
-
/* @__PURE__ */
|
|
1128
|
+
/* @__PURE__ */ jsx13(
|
|
897
1129
|
"div",
|
|
898
1130
|
{
|
|
899
1131
|
style: {
|
|
@@ -903,7 +1135,7 @@ function ArticleDetailHero({
|
|
|
903
1135
|
}
|
|
904
1136
|
}
|
|
905
1137
|
),
|
|
906
|
-
/* @__PURE__ */
|
|
1138
|
+
/* @__PURE__ */ jsxs13(
|
|
907
1139
|
"div",
|
|
908
1140
|
{
|
|
909
1141
|
style: {
|
|
@@ -917,7 +1149,7 @@ function ArticleDetailHero({
|
|
|
917
1149
|
width: "100%"
|
|
918
1150
|
},
|
|
919
1151
|
children: [
|
|
920
|
-
article.categories && article.categories.length > 0 && /* @__PURE__ */
|
|
1152
|
+
article.categories && article.categories.length > 0 && /* @__PURE__ */ jsx13(
|
|
921
1153
|
"div",
|
|
922
1154
|
{
|
|
923
1155
|
style: {
|
|
@@ -928,15 +1160,15 @@ function ArticleDetailHero({
|
|
|
928
1160
|
marginBottom: "1rem"
|
|
929
1161
|
},
|
|
930
1162
|
children: article.categories.slice(0, 4).map(
|
|
931
|
-
(cat) => categoryBasePath ? /* @__PURE__ */
|
|
932
|
-
|
|
1163
|
+
(cat) => categoryBasePath ? /* @__PURE__ */ jsx13(
|
|
1164
|
+
Link8,
|
|
933
1165
|
{
|
|
934
1166
|
href: `${categoryBasePath}/${toSlug(cat)}`,
|
|
935
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",
|
|
936
1168
|
children: cat
|
|
937
1169
|
},
|
|
938
1170
|
cat
|
|
939
|
-
) : /* @__PURE__ */
|
|
1171
|
+
) : /* @__PURE__ */ jsx13(
|
|
940
1172
|
"span",
|
|
941
1173
|
{
|
|
942
1174
|
className: "inline-block bg-white/20 text-white text-sm font-medium px-3 py-1 rounded-full",
|
|
@@ -947,8 +1179,8 @@ function ArticleDetailHero({
|
|
|
947
1179
|
)
|
|
948
1180
|
}
|
|
949
1181
|
),
|
|
950
|
-
/* @__PURE__ */
|
|
951
|
-
/* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ jsx13("h1", { className: "text-4xl md:text-5xl font-bold mb-4", children: article.title }),
|
|
1183
|
+
/* @__PURE__ */ jsxs13(
|
|
952
1184
|
"div",
|
|
953
1185
|
{
|
|
954
1186
|
style: {
|
|
@@ -960,23 +1192,23 @@ function ArticleDetailHero({
|
|
|
960
1192
|
color: "rgba(255,255,255,0.8)"
|
|
961
1193
|
},
|
|
962
1194
|
children: [
|
|
963
|
-
showDate && article.date && /* @__PURE__ */
|
|
964
|
-
/* @__PURE__ */
|
|
965
|
-
/* @__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 })
|
|
966
1198
|
] }),
|
|
967
|
-
/* @__PURE__ */
|
|
968
|
-
/* @__PURE__ */
|
|
969
|
-
/* @__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 })
|
|
970
1202
|
] }),
|
|
971
|
-
showConfiguredAuthors && /* @__PURE__ */
|
|
972
|
-
/* @__PURE__ */
|
|
973
|
-
/* @__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: [
|
|
974
1206
|
"By",
|
|
975
1207
|
" ",
|
|
976
|
-
authors.map((author, index) => /* @__PURE__ */
|
|
1208
|
+
authors.map((author, index) => /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
977
1209
|
index > 0 && ", ",
|
|
978
|
-
/* @__PURE__ */
|
|
979
|
-
|
|
1210
|
+
/* @__PURE__ */ jsx13(
|
|
1211
|
+
Link8,
|
|
980
1212
|
{
|
|
981
1213
|
href: `/articles/authors/${author.slug}`,
|
|
982
1214
|
className: "font-medium text-white underline-offset-4 hover:underline",
|
|
@@ -986,15 +1218,26 @@ function ArticleDetailHero({
|
|
|
986
1218
|
] }, author.slug))
|
|
987
1219
|
] })
|
|
988
1220
|
] }),
|
|
989
|
-
showLegacyAuthor && /* @__PURE__ */
|
|
990
|
-
/* @__PURE__ */
|
|
991
|
-
/* @__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: [
|
|
992
1224
|
"By ",
|
|
993
1225
|
article.author
|
|
994
1226
|
] })
|
|
995
1227
|
] })
|
|
996
1228
|
]
|
|
997
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
|
+
}
|
|
998
1241
|
)
|
|
999
1242
|
]
|
|
1000
1243
|
}
|
|
@@ -1005,9 +1248,9 @@ function ArticleDetailHero({
|
|
|
1005
1248
|
}
|
|
1006
1249
|
|
|
1007
1250
|
// src/CategoryArticlesPage.tsx
|
|
1008
|
-
import
|
|
1009
|
-
import
|
|
1010
|
-
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";
|
|
1011
1254
|
function getCategoryDescription(config, slug, categoryName) {
|
|
1012
1255
|
var _a;
|
|
1013
1256
|
const raw = (_a = config.categoryDescriptions) == null ? void 0 : _a[slug];
|
|
@@ -1049,7 +1292,14 @@ function buildCategoryBreadcrumbEntry(entry, context) {
|
|
|
1049
1292
|
}
|
|
1050
1293
|
return [{ name: context.categoryName }];
|
|
1051
1294
|
}
|
|
1052
|
-
function CategoryArticlesPage({
|
|
1295
|
+
function CategoryArticlesPage({
|
|
1296
|
+
category,
|
|
1297
|
+
articles,
|
|
1298
|
+
config,
|
|
1299
|
+
page,
|
|
1300
|
+
totalPages,
|
|
1301
|
+
totalCount
|
|
1302
|
+
}) {
|
|
1053
1303
|
var _a;
|
|
1054
1304
|
if (articles.length === 0) return null;
|
|
1055
1305
|
const categoryName = articles[0].category;
|
|
@@ -1058,8 +1308,25 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1058
1308
|
const pageSize = (_a = config.pageSize) != null ? _a : DEFAULT_PAGE_SIZE;
|
|
1059
1309
|
const breadcrumbConfig = getBreadcrumbsConfig(config);
|
|
1060
1310
|
const breadcrumbItems = buildCategoryBreadcrumbItems(config, categoryName);
|
|
1061
|
-
|
|
1062
|
-
|
|
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(
|
|
1063
1330
|
Breadcrumb,
|
|
1064
1331
|
{
|
|
1065
1332
|
items: breadcrumbItems,
|
|
@@ -1067,7 +1334,7 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1067
1334
|
showSchema: breadcrumbConfig.showSchema !== false
|
|
1068
1335
|
}
|
|
1069
1336
|
),
|
|
1070
|
-
/* @__PURE__ */
|
|
1337
|
+
/* @__PURE__ */ jsxs14(
|
|
1071
1338
|
"section",
|
|
1072
1339
|
{
|
|
1073
1340
|
style: {
|
|
@@ -1079,8 +1346,8 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1079
1346
|
overflow: "hidden"
|
|
1080
1347
|
},
|
|
1081
1348
|
children: [
|
|
1082
|
-
/* @__PURE__ */
|
|
1083
|
-
|
|
1349
|
+
/* @__PURE__ */ jsx14(
|
|
1350
|
+
Image6,
|
|
1084
1351
|
{
|
|
1085
1352
|
src: heroImage,
|
|
1086
1353
|
alt: categoryName,
|
|
@@ -1090,8 +1357,8 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1090
1357
|
priority: true
|
|
1091
1358
|
}
|
|
1092
1359
|
),
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1360
|
+
/* @__PURE__ */ jsx14("div", { style: { position: "absolute", inset: 0, backgroundColor: "rgba(0,0,0,0.6)" } }),
|
|
1361
|
+
/* @__PURE__ */ jsxs14(
|
|
1095
1362
|
"div",
|
|
1096
1363
|
{
|
|
1097
1364
|
style: {
|
|
@@ -1102,10 +1369,10 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1102
1369
|
padding: "0 1rem"
|
|
1103
1370
|
},
|
|
1104
1371
|
children: [
|
|
1105
|
-
/* @__PURE__ */
|
|
1106
|
-
/* @__PURE__ */
|
|
1107
|
-
description.long && /* @__PURE__ */
|
|
1108
|
-
/* @__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: [
|
|
1109
1376
|
articles.length,
|
|
1110
1377
|
" article",
|
|
1111
1378
|
articles.length === 1 ? "" : "s"
|
|
@@ -1116,150 +1383,75 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1116
1383
|
]
|
|
1117
1384
|
}
|
|
1118
1385
|
),
|
|
1119
|
-
/* @__PURE__ */
|
|
1120
|
-
/* @__PURE__ */
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__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 })
|
|
1123
1390
|
] }),
|
|
1124
|
-
/* @__PURE__ */
|
|
1391
|
+
/* @__PURE__ */ jsx14(LatestArticles, { articles, pageSize, pagination })
|
|
1125
1392
|
] }) })
|
|
1126
1393
|
] });
|
|
1127
1394
|
}
|
|
1128
1395
|
|
|
1129
|
-
// src/
|
|
1130
|
-
import
|
|
1131
|
-
import { jsx as
|
|
1132
|
-
function
|
|
1133
|
-
var _a, _b;
|
|
1134
|
-
return __spreadProps(__spreadValues(__spreadValues({
|
|
1135
|
-
"@context": "https://schema.org",
|
|
1136
|
-
"@type": "Person",
|
|
1137
|
-
name: author.name,
|
|
1138
|
-
description: author.bio,
|
|
1139
|
-
url: (_a = author.url) != null ? _a : getAuthorUrl(author)
|
|
1140
|
-
}, getAuthorAvatar(author, config) && { image: getAuthorAvatar(author, config) }), getAuthorSameAs(author).length > 0 && { sameAs: getAuthorSameAs(author) }), {
|
|
1141
|
-
knowsAbout: config.siteName,
|
|
1142
|
-
mainEntityOfPage: (_b = author.url) != null ? _b : `${config.siteUrl.replace(/\/$/, "")}/articles/authors/${author.slug}`,
|
|
1143
|
-
interactionStatistic: {
|
|
1144
|
-
"@type": "InteractionCounter",
|
|
1145
|
-
interactionType: "https://schema.org/WriteAction",
|
|
1146
|
-
userInteractionCount: articleCount
|
|
1147
|
-
}
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
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 }) {
|
|
1151
1400
|
var _a;
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
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,
|
|
1156
1408
|
{
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
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
|
+
}))
|
|
1161
1418
|
}
|
|
1162
1419
|
),
|
|
1163
|
-
/* @__PURE__ */
|
|
1164
|
-
/* @__PURE__ */
|
|
1165
|
-
/* @__PURE__ */
|
|
1166
|
-
/* @__PURE__ */
|
|
1167
|
-
|
|
1168
|
-
|
|
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"
|
|
1169
1428
|
] })
|
|
1170
1429
|
] }),
|
|
1171
|
-
/* @__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
|
+
)
|
|
1172
1438
|
] }) })
|
|
1173
1439
|
] });
|
|
1174
1440
|
}
|
|
1175
1441
|
|
|
1176
|
-
// src/
|
|
1177
|
-
import
|
|
1178
|
-
import Link9 from "next/link";
|
|
1179
|
-
import {
|
|
1180
|
-
Facebook,
|
|
1181
|
-
Github,
|
|
1182
|
-
Globe,
|
|
1183
|
-
Instagram,
|
|
1184
|
-
Linkedin,
|
|
1185
|
-
Mail,
|
|
1186
|
-
MessageCircle,
|
|
1187
|
-
Twitter,
|
|
1188
|
-
Youtube
|
|
1189
|
-
} from "lucide-react";
|
|
1190
|
-
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1191
|
-
function getInitials(name) {
|
|
1192
|
-
return name.split(" ").filter(Boolean).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
|
|
1193
|
-
}
|
|
1194
|
-
function AuthorCard({
|
|
1195
|
-
author,
|
|
1196
|
-
linkToPage = true,
|
|
1197
|
-
showBio = false,
|
|
1198
|
-
showSocial = false
|
|
1199
|
-
}) {
|
|
1200
|
-
const avatar = getAuthorAvatar(author);
|
|
1201
|
-
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 });
|
|
1202
|
-
return /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3 rounded-lg border border-border bg-card p-4 text-card-foreground", children: [
|
|
1203
|
-
avatar ? /* @__PURE__ */ jsx14(
|
|
1204
|
-
Image6,
|
|
1205
|
-
{
|
|
1206
|
-
src: avatar,
|
|
1207
|
-
alt: author.name,
|
|
1208
|
-
width: 48,
|
|
1209
|
-
height: 48,
|
|
1210
|
-
className: "h-12 w-12 rounded-full object-cover"
|
|
1211
|
-
}
|
|
1212
|
-
) : /* @__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) }),
|
|
1213
|
-
/* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
|
|
1214
|
-
name,
|
|
1215
|
-
showBio && author.bio && /* @__PURE__ */ jsx14("p", { className: "mt-1 line-clamp-2 text-sm text-muted-foreground", children: author.bio }),
|
|
1216
|
-
showSocial && /* @__PURE__ */ jsx14(AuthorSocialLinks, { author })
|
|
1217
|
-
] })
|
|
1218
|
-
] });
|
|
1219
|
-
}
|
|
1220
|
-
var SOCIAL_ICONS = {
|
|
1221
|
-
Website: Globe,
|
|
1222
|
-
Facebook,
|
|
1223
|
-
Twitter,
|
|
1224
|
-
X: Twitter,
|
|
1225
|
-
LinkedIn: Linkedin,
|
|
1226
|
-
Instagram,
|
|
1227
|
-
YouTube: Youtube,
|
|
1228
|
-
GitHub: Github,
|
|
1229
|
-
Newsletter: Mail
|
|
1230
|
-
};
|
|
1231
|
-
function getSocialIcon(label) {
|
|
1232
|
-
var _a;
|
|
1233
|
-
return (_a = SOCIAL_ICONS[label]) != null ? _a : MessageCircle;
|
|
1234
|
-
}
|
|
1235
|
-
function AuthorSocialLinks({ author }) {
|
|
1236
|
-
const links = getAuthorSocialLinks(author);
|
|
1237
|
-
if (links.length === 0) return null;
|
|
1238
|
-
return /* @__PURE__ */ jsx14("div", { className: "mt-3 flex items-center gap-2", children: links.map(({ href, label }) => {
|
|
1239
|
-
const Icon = getSocialIcon(label);
|
|
1240
|
-
return /* @__PURE__ */ jsx14(
|
|
1241
|
-
Link9,
|
|
1242
|
-
{
|
|
1243
|
-
href,
|
|
1244
|
-
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",
|
|
1245
|
-
"aria-label": `${author.name} on ${label}`,
|
|
1246
|
-
children: /* @__PURE__ */ jsx14(Icon, { className: "h-4 w-4" })
|
|
1247
|
-
},
|
|
1248
|
-
`${label}-${href}`
|
|
1249
|
-
);
|
|
1250
|
-
}) });
|
|
1251
|
-
}
|
|
1442
|
+
// src/AuthorArticlesPage.tsx
|
|
1443
|
+
import Link11 from "next/link";
|
|
1252
1444
|
|
|
1253
1445
|
// src/AuthorDetailHero.tsx
|
|
1254
1446
|
import Image7 from "next/image";
|
|
1255
|
-
import { jsx as
|
|
1447
|
+
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1256
1448
|
function getInitials2(name) {
|
|
1257
1449
|
return name.split(" ").filter(Boolean).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
|
|
1258
1450
|
}
|
|
1259
1451
|
function AuthorDetailHero({ author, articleCount }) {
|
|
1260
1452
|
const avatar = getAuthorAvatar(author);
|
|
1261
|
-
return /* @__PURE__ */
|
|
1262
|
-
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(
|
|
1263
1455
|
Image7,
|
|
1264
1456
|
{
|
|
1265
1457
|
src: avatar,
|
|
@@ -1269,27 +1461,303 @@ function AuthorDetailHero({ author, articleCount }) {
|
|
|
1269
1461
|
className: "h-28 w-28 rounded-full object-cover",
|
|
1270
1462
|
priority: true
|
|
1271
1463
|
}
|
|
1272
|
-
) : /* @__PURE__ */
|
|
1273
|
-
/* @__PURE__ */
|
|
1274
|
-
/* @__PURE__ */
|
|
1275
|
-
/* @__PURE__ */
|
|
1276
|
-
/* @__PURE__ */
|
|
1277
|
-
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: [
|
|
1278
1470
|
articleCount,
|
|
1279
1471
|
" article",
|
|
1280
1472
|
articleCount === 1 ? "" : "s"
|
|
1281
1473
|
] })
|
|
1282
1474
|
] }),
|
|
1283
|
-
/* @__PURE__ */
|
|
1475
|
+
/* @__PURE__ */ jsx16(AuthorSocialLinks, { author })
|
|
1284
1476
|
] }) });
|
|
1285
1477
|
}
|
|
1286
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
|
+
|
|
1287
1744
|
// src/ArticleSocialShare.tsx
|
|
1288
1745
|
import { useState as useState4 } from "react";
|
|
1289
1746
|
import { Share2, Copy, Check, Mail as Mail2, MessageCircle as MessageCircle2, Users, FileText } from "lucide-react";
|
|
1290
|
-
import { jsx as
|
|
1291
|
-
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
|
+
}) {
|
|
1292
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
|
+
}
|
|
1293
1761
|
const encodedTitle = encodeURIComponent(title);
|
|
1294
1762
|
const encodedUrl = encodeURIComponent(url);
|
|
1295
1763
|
const encodedExcerpt = encodeURIComponent(excerpt || "");
|
|
@@ -1306,102 +1774,203 @@ function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
|
|
|
1306
1774
|
try {
|
|
1307
1775
|
yield navigator.clipboard.writeText(url);
|
|
1308
1776
|
setCopied(true);
|
|
1777
|
+
trackShare("copy-link");
|
|
1309
1778
|
setTimeout(() => setCopied(false), 2e3);
|
|
1310
1779
|
} catch (e) {
|
|
1311
1780
|
}
|
|
1312
1781
|
});
|
|
1313
|
-
const openShareWindow = (shareUrl) => {
|
|
1782
|
+
const openShareWindow = (shareUrl, channel) => {
|
|
1783
|
+
trackShare(channel);
|
|
1314
1784
|
globalThis.open(shareUrl, "_blank", "width=600,height=400,scrollbars=yes,resizable=yes");
|
|
1315
1785
|
};
|
|
1316
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";
|
|
1317
|
-
return /* @__PURE__ */
|
|
1318
|
-
/* @__PURE__ */
|
|
1319
|
-
/* @__PURE__ */
|
|
1320
|
-
/* @__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" })
|
|
1321
1791
|
] }),
|
|
1322
|
-
/* @__PURE__ */
|
|
1323
|
-
/* @__PURE__ */
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
/* @__PURE__ */
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
|
|
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" }),
|
|
1349
1867
|
"Email"
|
|
1350
1868
|
] }),
|
|
1351
|
-
/* @__PURE__ */
|
|
1352
|
-
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" }),
|
|
1353
1871
|
copied ? "Copied!" : "Copy Link"
|
|
1354
1872
|
] })
|
|
1355
1873
|
] }),
|
|
1356
|
-
shareMessage && /* @__PURE__ */
|
|
1874
|
+
shareMessage && /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground mt-3", children: shareMessage })
|
|
1357
1875
|
] });
|
|
1358
1876
|
}
|
|
1359
1877
|
|
|
1360
1878
|
// src/ArticleNavigation.tsx
|
|
1361
|
-
import
|
|
1362
|
-
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
1363
|
-
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";
|
|
1364
1882
|
function truncateTitle(title, maxLength = 60) {
|
|
1365
1883
|
return title.length > maxLength ? `${title.substring(0, maxLength)}...` : title;
|
|
1366
1884
|
}
|
|
1367
|
-
function ArticleNavigation({
|
|
1885
|
+
function ArticleNavigation({
|
|
1886
|
+
previous,
|
|
1887
|
+
next,
|
|
1888
|
+
basePath,
|
|
1889
|
+
fromSlug,
|
|
1890
|
+
pathKey,
|
|
1891
|
+
config
|
|
1892
|
+
}) {
|
|
1368
1893
|
if (!previous && !next) return null;
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
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,
|
|
1372
1907
|
{
|
|
1373
1908
|
href: `${basePath}/${previous.slug}`,
|
|
1909
|
+
onClick: () => emitStep(previous.slug, "previous"),
|
|
1374
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",
|
|
1375
1911
|
children: [
|
|
1376
|
-
/* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1378
|
-
/* @__PURE__ */
|
|
1379
|
-
/* @__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) })
|
|
1380
1916
|
] })
|
|
1381
1917
|
]
|
|
1382
1918
|
}
|
|
1383
1919
|
) }),
|
|
1384
|
-
/* @__PURE__ */
|
|
1385
|
-
|
|
1920
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: next && /* @__PURE__ */ jsxs19(
|
|
1921
|
+
Link12,
|
|
1386
1922
|
{
|
|
1387
1923
|
href: `${basePath}/${next.slug}`,
|
|
1924
|
+
onClick: () => emitStep(next.slug, "next"),
|
|
1388
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",
|
|
1389
1926
|
children: [
|
|
1390
|
-
/* @__PURE__ */
|
|
1391
|
-
/* @__PURE__ */
|
|
1392
|
-
/* @__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) })
|
|
1393
1930
|
] }),
|
|
1394
|
-
/* @__PURE__ */
|
|
1931
|
+
/* @__PURE__ */ jsx20(ChevronRight2, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" })
|
|
1395
1932
|
]
|
|
1396
1933
|
}
|
|
1397
1934
|
) })
|
|
1398
1935
|
] }) });
|
|
1399
1936
|
}
|
|
1400
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
|
+
|
|
1401
1970
|
// src/ArticleBackLink.tsx
|
|
1402
|
-
import
|
|
1971
|
+
import Link13 from "next/link";
|
|
1403
1972
|
import { ArrowLeft } from "lucide-react";
|
|
1404
|
-
import { jsx as
|
|
1973
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1405
1974
|
function ArticleBackLink({
|
|
1406
1975
|
config,
|
|
1407
1976
|
href = "/articles",
|
|
@@ -1409,13 +1978,13 @@ function ArticleBackLink({
|
|
|
1409
1978
|
className
|
|
1410
1979
|
}) {
|
|
1411
1980
|
if (config.showBackToArticles === false) return null;
|
|
1412
|
-
return /* @__PURE__ */
|
|
1413
|
-
|
|
1981
|
+
return /* @__PURE__ */ jsxs21(
|
|
1982
|
+
Link13,
|
|
1414
1983
|
{
|
|
1415
1984
|
href,
|
|
1416
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",
|
|
1417
1986
|
children: [
|
|
1418
|
-
/* @__PURE__ */
|
|
1987
|
+
/* @__PURE__ */ jsx22(ArrowLeft, { className: "h-4 w-4" }),
|
|
1419
1988
|
label
|
|
1420
1989
|
]
|
|
1421
1990
|
}
|
|
@@ -1423,17 +1992,17 @@ function ArticleBackLink({
|
|
|
1423
1992
|
}
|
|
1424
1993
|
|
|
1425
1994
|
// src/ArticleTOC.tsx
|
|
1426
|
-
import { jsx as
|
|
1995
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1427
1996
|
function ArticleTOC({ toc, className }) {
|
|
1428
1997
|
if (!toc.length) return null;
|
|
1429
|
-
return /* @__PURE__ */
|
|
1998
|
+
return /* @__PURE__ */ jsxs22(
|
|
1430
1999
|
"nav",
|
|
1431
2000
|
{
|
|
1432
2001
|
"aria-label": "Table of contents",
|
|
1433
2002
|
className: `mb-8 rounded-lg border border-border bg-muted/40 px-6 py-4 ${className != null ? className : ""}`,
|
|
1434
2003
|
children: [
|
|
1435
|
-
/* @__PURE__ */
|
|
1436
|
-
/* @__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(
|
|
1437
2006
|
"a",
|
|
1438
2007
|
{
|
|
1439
2008
|
href: `#${item.id}`,
|
|
@@ -1447,35 +2016,35 @@ function ArticleTOC({ toc, className }) {
|
|
|
1447
2016
|
}
|
|
1448
2017
|
|
|
1449
2018
|
// src/ScrollToTop.tsx
|
|
1450
|
-
import { useEffect as
|
|
2019
|
+
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
1451
2020
|
import { ArrowUp } from "lucide-react";
|
|
1452
|
-
import { jsx as
|
|
2021
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1453
2022
|
function ScrollToTop() {
|
|
1454
2023
|
const [visible, setVisible] = useState5(false);
|
|
1455
|
-
|
|
2024
|
+
useEffect5(() => {
|
|
1456
2025
|
const onScroll = () => setVisible(globalThis.scrollY > 300);
|
|
1457
2026
|
globalThis.addEventListener("scroll", onScroll, { passive: true });
|
|
1458
2027
|
return () => globalThis.removeEventListener("scroll", onScroll);
|
|
1459
2028
|
}, []);
|
|
1460
2029
|
if (!visible) return null;
|
|
1461
|
-
return /* @__PURE__ */
|
|
2030
|
+
return /* @__PURE__ */ jsx24(
|
|
1462
2031
|
"button",
|
|
1463
2032
|
{
|
|
1464
2033
|
"aria-label": "Scroll to top",
|
|
1465
2034
|
onClick: () => globalThis.scrollTo({ top: 0, behavior: "smooth" }),
|
|
1466
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",
|
|
1467
|
-
children: /* @__PURE__ */
|
|
2036
|
+
children: /* @__PURE__ */ jsx24(ArrowUp, { className: "h-5 w-5" })
|
|
1468
2037
|
}
|
|
1469
2038
|
);
|
|
1470
2039
|
}
|
|
1471
2040
|
|
|
1472
2041
|
// src/CommentsSection.tsx
|
|
1473
2042
|
import { useSession, signIn } from "next-auth/react";
|
|
1474
|
-
import { useCallback as useCallback2, useEffect as
|
|
2043
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useState as useState8 } from "react";
|
|
1475
2044
|
|
|
1476
2045
|
// src/CommentForm.tsx
|
|
1477
2046
|
import { useState as useState6 } from "react";
|
|
1478
|
-
import { jsx as
|
|
2047
|
+
import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1479
2048
|
var MAX_LENGTH = 2e3;
|
|
1480
2049
|
var WARN_THRESHOLD = 1800;
|
|
1481
2050
|
function submitLabel(submitting, parentId) {
|
|
@@ -1514,8 +2083,8 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1514
2083
|
}
|
|
1515
2084
|
});
|
|
1516
2085
|
}
|
|
1517
|
-
return /* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
2086
|
+
return /* @__PURE__ */ jsxs23("form", { onSubmit: handleSubmit, className: "space-y-2", children: [
|
|
2087
|
+
/* @__PURE__ */ jsx25(
|
|
1519
2088
|
"textarea",
|
|
1520
2089
|
{
|
|
1521
2090
|
value: body,
|
|
@@ -1528,13 +2097,13 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1528
2097
|
"aria-label": parentId ? "Reply text" : "Comment text"
|
|
1529
2098
|
}
|
|
1530
2099
|
),
|
|
1531
|
-
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: [
|
|
1532
2101
|
remaining,
|
|
1533
2102
|
" characters remaining"
|
|
1534
2103
|
] }),
|
|
1535
|
-
error && /* @__PURE__ */
|
|
1536
|
-
/* @__PURE__ */
|
|
1537
|
-
/* @__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(
|
|
1538
2107
|
"button",
|
|
1539
2108
|
{
|
|
1540
2109
|
type: "submit",
|
|
@@ -1543,7 +2112,7 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1543
2112
|
children: submitLabel(submitting, parentId)
|
|
1544
2113
|
}
|
|
1545
2114
|
),
|
|
1546
|
-
onCancel && /* @__PURE__ */
|
|
2115
|
+
onCancel && /* @__PURE__ */ jsx25(
|
|
1547
2116
|
"button",
|
|
1548
2117
|
{
|
|
1549
2118
|
type: "button",
|
|
@@ -1558,7 +2127,7 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1558
2127
|
|
|
1559
2128
|
// src/CommentItem.tsx
|
|
1560
2129
|
import { useState as useState7 } from "react";
|
|
1561
|
-
import { Fragment as
|
|
2130
|
+
import { Fragment as Fragment5, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1562
2131
|
function relativeTime(iso) {
|
|
1563
2132
|
const diff = Date.now() - new Date(iso).getTime();
|
|
1564
2133
|
const minutes = Math.floor(diff / 6e4);
|
|
@@ -1596,15 +2165,15 @@ function CommentItem({
|
|
|
1596
2165
|
}
|
|
1597
2166
|
});
|
|
1598
2167
|
}
|
|
1599
|
-
return /* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
/* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
/* @__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) })
|
|
1604
2173
|
] }),
|
|
1605
|
-
/* @__PURE__ */
|
|
1606
|
-
/* @__PURE__ */
|
|
1607
|
-
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(
|
|
1608
2177
|
"button",
|
|
1609
2178
|
{
|
|
1610
2179
|
onClick: () => setShowReplyForm((v) => !v),
|
|
@@ -1612,7 +2181,7 @@ function CommentItem({
|
|
|
1612
2181
|
children: showReplyForm ? "Cancel" : "Reply"
|
|
1613
2182
|
}
|
|
1614
2183
|
),
|
|
1615
|
-
canDelete && /* @__PURE__ */
|
|
2184
|
+
canDelete && /* @__PURE__ */ jsx26(
|
|
1616
2185
|
"button",
|
|
1617
2186
|
{
|
|
1618
2187
|
onClick: handleDelete,
|
|
@@ -1623,7 +2192,7 @@ function CommentItem({
|
|
|
1623
2192
|
)
|
|
1624
2193
|
] })
|
|
1625
2194
|
] }) }),
|
|
1626
|
-
showReplyForm && /* @__PURE__ */
|
|
2195
|
+
showReplyForm && /* @__PURE__ */ jsx26("div", { className: "mt-2 ml-2", children: /* @__PURE__ */ jsx26(
|
|
1627
2196
|
CommentForm,
|
|
1628
2197
|
{
|
|
1629
2198
|
articleSlug,
|
|
@@ -1635,7 +2204,7 @@ function CommentItem({
|
|
|
1635
2204
|
onCancel: () => setShowReplyForm(false)
|
|
1636
2205
|
}
|
|
1637
2206
|
) }),
|
|
1638
|
-
replies.length > 0 && /* @__PURE__ */
|
|
2207
|
+
replies.length > 0 && /* @__PURE__ */ jsx26("div", { className: "mt-2 space-y-2", children: replies.map((reply) => /* @__PURE__ */ jsx26(
|
|
1639
2208
|
CommentItem,
|
|
1640
2209
|
{
|
|
1641
2210
|
comment: __spreadProps(__spreadValues({}, reply), { replies: [] }),
|
|
@@ -1650,7 +2219,7 @@ function CommentItem({
|
|
|
1650
2219
|
}
|
|
1651
2220
|
|
|
1652
2221
|
// src/CommentThread.tsx
|
|
1653
|
-
import { jsx as
|
|
2222
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
1654
2223
|
function CommentThread({
|
|
1655
2224
|
comments,
|
|
1656
2225
|
articleSlug,
|
|
@@ -1658,9 +2227,9 @@ function CommentThread({
|
|
|
1658
2227
|
onRefresh
|
|
1659
2228
|
}) {
|
|
1660
2229
|
if (comments.length === 0) {
|
|
1661
|
-
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." });
|
|
1662
2231
|
}
|
|
1663
|
-
return /* @__PURE__ */
|
|
2232
|
+
return /* @__PURE__ */ jsx27("div", { className: "space-y-4", children: comments.map((comment) => /* @__PURE__ */ jsx27(
|
|
1664
2233
|
CommentItem,
|
|
1665
2234
|
{
|
|
1666
2235
|
comment,
|
|
@@ -1673,7 +2242,7 @@ function CommentThread({
|
|
|
1673
2242
|
}
|
|
1674
2243
|
|
|
1675
2244
|
// src/CommentsSection.tsx
|
|
1676
|
-
import { jsx as
|
|
2245
|
+
import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1677
2246
|
function CommentsSection({ articleSlug, config }) {
|
|
1678
2247
|
var _a, _b, _c, _d, _e, _f;
|
|
1679
2248
|
const { data: session, status } = useSession();
|
|
@@ -1697,7 +2266,7 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1697
2266
|
setLoading(false);
|
|
1698
2267
|
}
|
|
1699
2268
|
}), [articleSlug]);
|
|
1700
|
-
|
|
2269
|
+
useEffect6(() => {
|
|
1701
2270
|
if (enabled) {
|
|
1702
2271
|
fetchComments().catch(() => void 0);
|
|
1703
2272
|
}
|
|
@@ -1705,10 +2274,10 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1705
2274
|
if (!enabled) return null;
|
|
1706
2275
|
const count = comments.length;
|
|
1707
2276
|
const label = count === 1 ? "1 comment" : `${count} comments`;
|
|
1708
|
-
return /* @__PURE__ */
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
status === "authenticated" ? /* @__PURE__ */
|
|
1711
|
-
/* @__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(
|
|
1712
2281
|
"button",
|
|
1713
2282
|
{
|
|
1714
2283
|
onClick: () => signIn(),
|
|
@@ -1719,8 +2288,8 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1719
2288
|
" ",
|
|
1720
2289
|
"to join the discussion."
|
|
1721
2290
|
] }),
|
|
1722
|
-
fetchError && /* @__PURE__ */
|
|
1723
|
-
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(
|
|
1724
2293
|
CommentThread,
|
|
1725
2294
|
{
|
|
1726
2295
|
comments,
|
|
@@ -1738,10 +2307,10 @@ export {
|
|
|
1738
2307
|
ArticleDetailHero,
|
|
1739
2308
|
ArticleNavigation,
|
|
1740
2309
|
ArticleSEO,
|
|
1741
|
-
ArticleSchema,
|
|
1742
2310
|
ArticleSearchBar,
|
|
1743
2311
|
ArticleSocialShare,
|
|
1744
2312
|
ArticleTOC,
|
|
2313
|
+
ArticleViewTracker,
|
|
1745
2314
|
ArticlesHero,
|
|
1746
2315
|
ArticlesPage,
|
|
1747
2316
|
AuthorArticlesPage,
|
|
@@ -1756,6 +2325,7 @@ export {
|
|
|
1756
2325
|
CommentItem,
|
|
1757
2326
|
CommentThread,
|
|
1758
2327
|
CommentsSection,
|
|
2328
|
+
CtaViewTracker,
|
|
1759
2329
|
DEFAULT_CATEGORIES_PAGE_SIZE,
|
|
1760
2330
|
DEFAULT_LAYOUT,
|
|
1761
2331
|
DEFAULT_PAGE_SIZE,
|
|
@@ -1763,7 +2333,10 @@ export {
|
|
|
1763
2333
|
FeaturedArticle,
|
|
1764
2334
|
LatestArticles,
|
|
1765
2335
|
LatestArticlesSection,
|
|
2336
|
+
PaginationNav,
|
|
2337
|
+
RelatedArticlesSection,
|
|
1766
2338
|
ScrollToTop,
|
|
2339
|
+
SeriesArticlesPage,
|
|
1767
2340
|
breadcrumbsAreEnabled,
|
|
1768
2341
|
getBreadcrumbsConfig,
|
|
1769
2342
|
useArticles
|