@fullstackdatasolutions/articles 0.12.0 → 1.1.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 +34 -0
- package/README.md +559 -11
- package/dist/index.cjs +984 -388
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +383 -21
- package/dist/index.d.ts +383 -21
- package/dist/index.js +968 -376
- 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 +149 -0
- package/dist/nextjs.d.ts +149 -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 +357 -3
- package/dist/server.d.ts +357 -3
- package/dist/server.js +643 -29
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/ArticleCard.tsx +42 -6
- package/src/ArticleContent.tsx +144 -5
- package/src/ArticleDetailHero.tsx +33 -1
- package/src/ArticleNavigation.tsx +32 -1
- package/src/ArticleSchemas.tsx +43 -39
- package/src/ArticleSocialShare.tsx +54 -10
- package/src/ArticlesPage.tsx +56 -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 +58 -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 +45 -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,103 @@ 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
|
+
var _a;
|
|
593
|
+
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: [
|
|
594
|
+
/* @__PURE__ */ jsx8("div", { className: "p-0", children: /* @__PURE__ */ jsx8(
|
|
595
|
+
Image4,
|
|
520
596
|
{
|
|
521
597
|
src: article.featuredImage,
|
|
522
598
|
alt: article.title,
|
|
@@ -525,35 +601,67 @@ function ArticleCard({ article }) {
|
|
|
525
601
|
height: 200
|
|
526
602
|
}
|
|
527
603
|
) }),
|
|
528
|
-
/* @__PURE__ */
|
|
529
|
-
/* @__PURE__ */
|
|
530
|
-
/* @__PURE__ */
|
|
531
|
-
|
|
604
|
+
/* @__PURE__ */ jsxs8("div", { className: "p-6", children: [
|
|
605
|
+
/* @__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 }) }),
|
|
606
|
+
/* @__PURE__ */ jsx8(
|
|
607
|
+
"h3",
|
|
532
608
|
{
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
children: article.title
|
|
609
|
+
className: "text-lg font-semibold leading-none tracking-tight mb-2",
|
|
610
|
+
style: { fontFamily: (_a = config == null ? void 0 : config.theme) == null ? void 0 : _a.headerFontFamily },
|
|
611
|
+
children: /* @__PURE__ */ jsx8(Link6, { href: `/articles/${article.slug}`, className: "hover:text-primary transition-colors", children: article.title })
|
|
536
612
|
}
|
|
537
|
-
)
|
|
538
|
-
/* @__PURE__ */
|
|
539
|
-
/* @__PURE__ */
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
613
|
+
),
|
|
614
|
+
/* @__PURE__ */ jsx8("p", { className: "text-muted-foreground mb-4 line-clamp-3", children: article.excerpt }),
|
|
615
|
+
article.authorSlug && /* @__PURE__ */ jsxs8(
|
|
616
|
+
Link6,
|
|
617
|
+
{
|
|
618
|
+
href: `/articles/authors/${article.authorSlug}`,
|
|
619
|
+
className: "mb-4 flex items-center gap-2 text-sm text-muted-foreground hover:text-primary transition-colors",
|
|
620
|
+
onClick: () => emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
621
|
+
name: "author_clicked",
|
|
622
|
+
articleSlug: article.slug,
|
|
623
|
+
authorSlug: article.authorSlug
|
|
624
|
+
}),
|
|
625
|
+
children: [
|
|
626
|
+
article.authorAvatar ? /* @__PURE__ */ jsx8(
|
|
627
|
+
Image4,
|
|
628
|
+
{
|
|
629
|
+
src: article.authorAvatar,
|
|
630
|
+
alt: "",
|
|
631
|
+
width: 24,
|
|
632
|
+
height: 24,
|
|
633
|
+
className: "h-6 w-6 rounded-full object-cover"
|
|
634
|
+
}
|
|
635
|
+
) : /* @__PURE__ */ jsx8(
|
|
636
|
+
"span",
|
|
637
|
+
{
|
|
638
|
+
"aria-hidden": "true",
|
|
639
|
+
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-muted text-[10px] font-semibold text-muted-foreground",
|
|
640
|
+
children: getInitials(article.author)
|
|
641
|
+
}
|
|
642
|
+
),
|
|
643
|
+
/* @__PURE__ */ jsx8("span", { children: article.author })
|
|
644
|
+
]
|
|
645
|
+
}
|
|
646
|
+
),
|
|
647
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between text-sm text-muted-foreground border-t pt-4", children: [
|
|
648
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
|
|
649
|
+
article.date && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
650
|
+
/* @__PURE__ */ jsx8(Calendar2, { className: "h-3 w-3" }),
|
|
651
|
+
/* @__PURE__ */ jsx8("span", { children: article.date })
|
|
544
652
|
] }),
|
|
545
|
-
/* @__PURE__ */
|
|
546
|
-
/* @__PURE__ */
|
|
547
|
-
/* @__PURE__ */
|
|
653
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
654
|
+
/* @__PURE__ */ jsx8(Clock2, { className: "h-3 w-3" }),
|
|
655
|
+
/* @__PURE__ */ jsx8("span", { children: article.readTime })
|
|
548
656
|
] })
|
|
549
657
|
] }),
|
|
550
|
-
/* @__PURE__ */
|
|
551
|
-
|
|
658
|
+
/* @__PURE__ */ jsx8(
|
|
659
|
+
Link6,
|
|
552
660
|
{
|
|
553
661
|
href: `/articles/${article.slug}`,
|
|
554
662
|
className: "inline-flex items-center justify-center h-8 w-8 p-0 rounded-md hover:bg-accent transition-colors",
|
|
555
663
|
"aria-label": `Read ${article.title}`,
|
|
556
|
-
children: /* @__PURE__ */
|
|
664
|
+
children: /* @__PURE__ */ jsx8(ArrowRight2, { className: "h-4 w-4" })
|
|
557
665
|
}
|
|
558
666
|
)
|
|
559
667
|
] })
|
|
@@ -561,18 +669,114 @@ function ArticleCard({ article }) {
|
|
|
561
669
|
] });
|
|
562
670
|
}
|
|
563
671
|
|
|
672
|
+
// src/PaginationNav.tsx
|
|
673
|
+
import Link7 from "next/link";
|
|
674
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
675
|
+
|
|
676
|
+
// src/pagination.ts
|
|
677
|
+
function buildPageUrl(basePath, page) {
|
|
678
|
+
const base = basePath.replace(/\/$/, "");
|
|
679
|
+
return page > 1 ? `${base}/page/${page}` : base;
|
|
680
|
+
}
|
|
681
|
+
function buildPaginationLinks(basePath, page, totalPages) {
|
|
682
|
+
return {
|
|
683
|
+
canonicalUrl: buildPageUrl(basePath, page),
|
|
684
|
+
prevUrl: page > 1 ? buildPageUrl(basePath, page - 1) : null,
|
|
685
|
+
nextUrl: page < totalPages ? buildPageUrl(basePath, page + 1) : null
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// src/PaginationNav.tsx
|
|
690
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
691
|
+
function PaginationNav({ basePath, page, totalPages }) {
|
|
692
|
+
if (totalPages <= 1) return null;
|
|
693
|
+
const { prevUrl, nextUrl } = buildPaginationLinks(basePath, page, totalPages);
|
|
694
|
+
return /* @__PURE__ */ jsxs9(
|
|
695
|
+
"nav",
|
|
696
|
+
{
|
|
697
|
+
className: "mt-10 flex items-center justify-center gap-4",
|
|
698
|
+
"aria-label": "Article listing pagination",
|
|
699
|
+
children: [
|
|
700
|
+
prevUrl && /* @__PURE__ */ jsx9("link", { rel: "prev", href: prevUrl }),
|
|
701
|
+
nextUrl && /* @__PURE__ */ jsx9("link", { rel: "next", href: nextUrl }),
|
|
702
|
+
prevUrl ? /* @__PURE__ */ jsxs9(
|
|
703
|
+
Link7,
|
|
704
|
+
{
|
|
705
|
+
href: prevUrl,
|
|
706
|
+
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",
|
|
707
|
+
children: [
|
|
708
|
+
/* @__PURE__ */ jsx9(ChevronLeft, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
709
|
+
"Previous"
|
|
710
|
+
]
|
|
711
|
+
}
|
|
712
|
+
) : /* @__PURE__ */ jsxs9(
|
|
713
|
+
"span",
|
|
714
|
+
{
|
|
715
|
+
"aria-hidden": "true",
|
|
716
|
+
className: "inline-flex items-center gap-1 px-4 py-2 rounded-md font-medium text-sm text-muted-foreground opacity-50",
|
|
717
|
+
children: [
|
|
718
|
+
/* @__PURE__ */ jsx9(ChevronLeft, { className: "h-4 w-4" }),
|
|
719
|
+
"Previous"
|
|
720
|
+
]
|
|
721
|
+
}
|
|
722
|
+
),
|
|
723
|
+
/* @__PURE__ */ jsxs9("span", { className: "text-sm text-muted-foreground", children: [
|
|
724
|
+
"Page ",
|
|
725
|
+
page,
|
|
726
|
+
" of ",
|
|
727
|
+
totalPages
|
|
728
|
+
] }),
|
|
729
|
+
nextUrl ? /* @__PURE__ */ jsxs9(
|
|
730
|
+
Link7,
|
|
731
|
+
{
|
|
732
|
+
href: nextUrl,
|
|
733
|
+
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",
|
|
734
|
+
children: [
|
|
735
|
+
"Next",
|
|
736
|
+
/* @__PURE__ */ jsx9(ChevronRight, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
737
|
+
]
|
|
738
|
+
}
|
|
739
|
+
) : /* @__PURE__ */ jsxs9(
|
|
740
|
+
"span",
|
|
741
|
+
{
|
|
742
|
+
"aria-hidden": "true",
|
|
743
|
+
className: "inline-flex items-center gap-1 px-4 py-2 rounded-md font-medium text-sm text-muted-foreground opacity-50",
|
|
744
|
+
children: [
|
|
745
|
+
"Next",
|
|
746
|
+
/* @__PURE__ */ jsx9(ChevronRight, { className: "h-4 w-4" })
|
|
747
|
+
]
|
|
748
|
+
}
|
|
749
|
+
)
|
|
750
|
+
]
|
|
751
|
+
}
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
|
|
564
755
|
// src/LatestArticles.tsx
|
|
565
|
-
import { jsx as
|
|
566
|
-
function LatestArticles({ articles, pageSize }) {
|
|
756
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
757
|
+
function LatestArticles({ articles, pageSize, pagination }) {
|
|
567
758
|
const [visibleCount, setVisibleCount] = useState2(pageSize);
|
|
568
759
|
useEffect2(() => {
|
|
569
760
|
setVisibleCount(pageSize);
|
|
570
761
|
}, [articles, pageSize]);
|
|
762
|
+
if (pagination) {
|
|
763
|
+
return /* @__PURE__ */ jsxs10("div", { children: [
|
|
764
|
+
/* @__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)) }),
|
|
765
|
+
/* @__PURE__ */ jsx10(
|
|
766
|
+
PaginationNav,
|
|
767
|
+
{
|
|
768
|
+
basePath: pagination.basePath,
|
|
769
|
+
page: pagination.page,
|
|
770
|
+
totalPages: pagination.totalPages
|
|
771
|
+
}
|
|
772
|
+
)
|
|
773
|
+
] });
|
|
774
|
+
}
|
|
571
775
|
const visible = articles.slice(0, visibleCount);
|
|
572
776
|
const hasMore = visibleCount < articles.length;
|
|
573
|
-
return /* @__PURE__ */
|
|
574
|
-
/* @__PURE__ */
|
|
575
|
-
hasMore && /* @__PURE__ */
|
|
777
|
+
return /* @__PURE__ */ jsxs10("div", { children: [
|
|
778
|
+
/* @__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)) }),
|
|
779
|
+
hasMore && /* @__PURE__ */ jsx10("div", { className: "mt-10 text-center", children: /* @__PURE__ */ jsx10(
|
|
576
780
|
"button",
|
|
577
781
|
{
|
|
578
782
|
type: "button",
|
|
@@ -585,35 +789,36 @@ function LatestArticles({ articles, pageSize }) {
|
|
|
585
789
|
}
|
|
586
790
|
|
|
587
791
|
// src/LatestArticlesSection.tsx
|
|
588
|
-
import { jsx as
|
|
792
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
589
793
|
function DescriptionText({
|
|
590
794
|
searchQuery,
|
|
591
795
|
count
|
|
592
796
|
}) {
|
|
593
797
|
const pluralSuffix = count === 1 ? "" : "s";
|
|
594
798
|
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__ */
|
|
799
|
+
return /* @__PURE__ */ jsx11("p", { className: "text-lg text-muted-foreground", children: text });
|
|
596
800
|
}
|
|
597
801
|
function LatestArticlesSection({
|
|
598
802
|
articles,
|
|
599
803
|
searchQuery,
|
|
600
804
|
onClearSearch,
|
|
601
|
-
pageSize = 6
|
|
805
|
+
pageSize = 6,
|
|
806
|
+
pagination
|
|
602
807
|
}) {
|
|
603
|
-
return /* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
605
|
-
/* @__PURE__ */
|
|
606
|
-
/* @__PURE__ */
|
|
808
|
+
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: [
|
|
809
|
+
/* @__PURE__ */ jsxs11("div", { className: "text-center mb-12", children: [
|
|
810
|
+
/* @__PURE__ */ jsx11("h2", { className: "text-3xl font-bold text-foreground mb-4", children: searchQuery ? "Search Results" : "Latest Articles" }),
|
|
811
|
+
/* @__PURE__ */ jsx11(DescriptionText, { searchQuery, count: articles.length })
|
|
607
812
|
] }),
|
|
608
|
-
articles.length === 0 && searchQuery ? /* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
610
|
-
/* @__PURE__ */
|
|
611
|
-
/* @__PURE__ */
|
|
813
|
+
articles.length === 0 && searchQuery ? /* @__PURE__ */ jsx11("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxs11("div", { className: "max-w-md mx-auto", children: [
|
|
814
|
+
/* @__PURE__ */ jsx11(Search2, { className: "h-12 w-12 text-muted-foreground mx-auto mb-4" }),
|
|
815
|
+
/* @__PURE__ */ jsx11("h3", { className: "text-lg font-semibold text-foreground mb-2", children: "No articles found" }),
|
|
816
|
+
/* @__PURE__ */ jsxs11("p", { className: "text-muted-foreground mb-4", children: [
|
|
612
817
|
`We couldn't find any articles matching "`,
|
|
613
818
|
searchQuery,
|
|
614
819
|
'". Try adjusting your search terms.'
|
|
615
820
|
] }),
|
|
616
|
-
/* @__PURE__ */
|
|
821
|
+
/* @__PURE__ */ jsx11(
|
|
617
822
|
"button",
|
|
618
823
|
{
|
|
619
824
|
type: "button",
|
|
@@ -622,7 +827,15 @@ function LatestArticlesSection({
|
|
|
622
827
|
children: "Clear search"
|
|
623
828
|
}
|
|
624
829
|
)
|
|
625
|
-
] }) }) : /* @__PURE__ */
|
|
830
|
+
] }) }) : /* @__PURE__ */ jsx11(
|
|
831
|
+
LatestArticles,
|
|
832
|
+
{
|
|
833
|
+
articles,
|
|
834
|
+
pageSize,
|
|
835
|
+
pagination: searchQuery ? void 0 : pagination
|
|
836
|
+
},
|
|
837
|
+
searchQuery
|
|
838
|
+
)
|
|
626
839
|
] }) });
|
|
627
840
|
}
|
|
628
841
|
|
|
@@ -715,11 +928,12 @@ function useArticles(initialArticles, initialCategories) {
|
|
|
715
928
|
}
|
|
716
929
|
|
|
717
930
|
// src/ArticlesPage.tsx
|
|
718
|
-
import { jsx as
|
|
931
|
+
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
719
932
|
function buildThemeVars(theme) {
|
|
720
933
|
if (!theme) return {};
|
|
721
934
|
const vars = {};
|
|
722
935
|
if (theme.fontFamily) vars["--articles-font-family"] = theme.fontFamily;
|
|
936
|
+
if (theme.headerFontFamily) vars["--articles-header-font-family"] = theme.headerFontFamily;
|
|
723
937
|
if (theme.headerColor) vars["--articles-header-color"] = theme.headerColor;
|
|
724
938
|
if (theme.textColor) vars["--articles-text-color"] = theme.textColor;
|
|
725
939
|
if (theme.backgroundColor) vars["--articles-bg-color"] = theme.backgroundColor;
|
|
@@ -744,11 +958,12 @@ function renderSection(section, ctx, config) {
|
|
|
744
958
|
error,
|
|
745
959
|
handleSearch,
|
|
746
960
|
pageSize,
|
|
747
|
-
categoriesPageSize
|
|
961
|
+
categoriesPageSize,
|
|
962
|
+
pagination
|
|
748
963
|
} = ctx;
|
|
749
964
|
switch (section) {
|
|
750
965
|
case "hero":
|
|
751
|
-
return /* @__PURE__ */
|
|
966
|
+
return /* @__PURE__ */ jsx12(
|
|
752
967
|
ArticlesHero,
|
|
753
968
|
{
|
|
754
969
|
title: (_a = config.hero) == null ? void 0 : _a.title,
|
|
@@ -757,7 +972,7 @@ function renderSection(section, ctx, config) {
|
|
|
757
972
|
"hero"
|
|
758
973
|
);
|
|
759
974
|
case "search":
|
|
760
|
-
return /* @__PURE__ */
|
|
975
|
+
return /* @__PURE__ */ jsx12(
|
|
761
976
|
ArticleSearchBar,
|
|
762
977
|
{
|
|
763
978
|
value: searchQuery,
|
|
@@ -768,7 +983,7 @@ function renderSection(section, ctx, config) {
|
|
|
768
983
|
"search"
|
|
769
984
|
);
|
|
770
985
|
case "featured":
|
|
771
|
-
return articles.length > 0 && !searchQuery ? /* @__PURE__ */
|
|
986
|
+
return articles.length > 0 && !searchQuery ? /* @__PURE__ */ jsx12(
|
|
772
987
|
FeaturedArticle,
|
|
773
988
|
{
|
|
774
989
|
article: articles[0],
|
|
@@ -778,16 +993,16 @@ function renderSection(section, ctx, config) {
|
|
|
778
993
|
) : null;
|
|
779
994
|
case "latest":
|
|
780
995
|
if (loading && articles.length === 0) {
|
|
781
|
-
return /* @__PURE__ */
|
|
782
|
-
/* @__PURE__ */
|
|
783
|
-
/* @__PURE__ */
|
|
996
|
+
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: [
|
|
997
|
+
/* @__PURE__ */ jsx12("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4" }),
|
|
998
|
+
/* @__PURE__ */ jsx12("p", { className: "text-muted-foreground", children: "Loading articles..." })
|
|
784
999
|
] }) }) }, "latest");
|
|
785
1000
|
}
|
|
786
1001
|
if (error) {
|
|
787
|
-
return /* @__PURE__ */
|
|
788
|
-
/* @__PURE__ */
|
|
789
|
-
/* @__PURE__ */
|
|
790
|
-
/* @__PURE__ */
|
|
1002
|
+
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: [
|
|
1003
|
+
/* @__PURE__ */ jsx12("h3", { className: "text-lg font-semibold text-red-800 mb-2", children: "Error Loading Articles" }),
|
|
1004
|
+
/* @__PURE__ */ jsx12("p", { className: "text-red-600 mb-4", children: error }),
|
|
1005
|
+
/* @__PURE__ */ jsx12(
|
|
791
1006
|
"button",
|
|
792
1007
|
{
|
|
793
1008
|
type: "button",
|
|
@@ -798,18 +1013,19 @@ function renderSection(section, ctx, config) {
|
|
|
798
1013
|
)
|
|
799
1014
|
] }) }) }, "latest");
|
|
800
1015
|
}
|
|
801
|
-
return /* @__PURE__ */
|
|
1016
|
+
return /* @__PURE__ */ jsx12(
|
|
802
1017
|
LatestArticlesSection,
|
|
803
1018
|
{
|
|
804
1019
|
articles: displayedArticles,
|
|
805
1020
|
searchQuery,
|
|
806
1021
|
onClearSearch: () => handleSearch(""),
|
|
807
|
-
pageSize
|
|
1022
|
+
pageSize,
|
|
1023
|
+
pagination
|
|
808
1024
|
},
|
|
809
1025
|
"latest"
|
|
810
1026
|
);
|
|
811
1027
|
case "categories":
|
|
812
|
-
return searchQuery ? null : /* @__PURE__ */
|
|
1028
|
+
return searchQuery ? null : /* @__PURE__ */ jsx12(
|
|
813
1029
|
ArticleCategoryGrid,
|
|
814
1030
|
{
|
|
815
1031
|
categories,
|
|
@@ -825,7 +1041,10 @@ function renderSection(section, ctx, config) {
|
|
|
825
1041
|
function ArticlesPage({
|
|
826
1042
|
config,
|
|
827
1043
|
initialArticles,
|
|
828
|
-
initialCategories
|
|
1044
|
+
initialCategories,
|
|
1045
|
+
page,
|
|
1046
|
+
totalPages,
|
|
1047
|
+
totalCount
|
|
829
1048
|
}) {
|
|
830
1049
|
var _a, _b, _c;
|
|
831
1050
|
const state = useArticles(initialArticles, initialCategories);
|
|
@@ -833,19 +1052,34 @@ function ArticlesPage({
|
|
|
833
1052
|
const pageSize = (_b = config.pageSize) != null ? _b : DEFAULT_PAGE_SIZE;
|
|
834
1053
|
const categoriesPageSize = (_c = config.categoriesPageSize) != null ? _c : DEFAULT_CATEGORIES_PAGE_SIZE;
|
|
835
1054
|
const themeVars = buildThemeVars(config.theme);
|
|
836
|
-
const
|
|
1055
|
+
const isPagesMode = config.listingPagination === "pages" && page !== void 0 && totalPages !== void 0;
|
|
1056
|
+
const currentPage = page != null ? page : 1;
|
|
1057
|
+
const effectiveLayout = isPagesMode && currentPage > 1 ? layout.filter((section) => section !== "featured") : layout;
|
|
1058
|
+
const hasFeatured = effectiveLayout.includes("featured");
|
|
837
1059
|
const articlesWithoutFeatured = hasFeatured ? state.articles.slice(1) : state.articles;
|
|
838
1060
|
const displayedArticles = state.searchQuery ? state.articles : articlesWithoutFeatured;
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1061
|
+
const pagination = isPagesMode ? { page: currentPage, totalPages, basePath: "/articles" } : void 0;
|
|
1062
|
+
const ctx = __spreadProps(__spreadValues({}, state), {
|
|
1063
|
+
displayedArticles,
|
|
1064
|
+
pageSize,
|
|
1065
|
+
categoriesPageSize,
|
|
1066
|
+
pagination
|
|
1067
|
+
});
|
|
1068
|
+
const articleCount = totalCount != null ? totalCount : state.articles.length;
|
|
1069
|
+
return /* @__PURE__ */ jsxs12("div", { style: themeVars, children: [
|
|
1070
|
+
effectiveLayout.map((section) => renderSection(section, ctx, config)),
|
|
1071
|
+
state.articles.length > 0 && /* @__PURE__ */ jsx12(
|
|
843
1072
|
CollectionPageSchema,
|
|
844
1073
|
{
|
|
845
1074
|
title: `Articles | ${config.siteName}`,
|
|
846
|
-
description: `Browse all ${
|
|
1075
|
+
description: `Browse all ${articleCount} articles on ${config.siteName}.`,
|
|
847
1076
|
url: `${config.siteUrl}/articles`,
|
|
848
|
-
articleCount
|
|
1077
|
+
articleCount,
|
|
1078
|
+
items: displayedArticles.slice(0, pageSize).map((article, index) => ({
|
|
1079
|
+
position: index + 1,
|
|
1080
|
+
url: `${config.siteUrl}/articles/${article.slug}`,
|
|
1081
|
+
name: article.title
|
|
1082
|
+
}))
|
|
849
1083
|
}
|
|
850
1084
|
)
|
|
851
1085
|
] });
|
|
@@ -853,10 +1087,10 @@ function ArticlesPage({
|
|
|
853
1087
|
|
|
854
1088
|
// src/ArticleDetailHero.tsx
|
|
855
1089
|
import { Fragment as Fragment3 } from "react";
|
|
856
|
-
import
|
|
857
|
-
import
|
|
1090
|
+
import Image5 from "next/image";
|
|
1091
|
+
import Link8 from "next/link";
|
|
858
1092
|
import { Calendar as Calendar3, Clock as Clock3, User as User2 } from "lucide-react";
|
|
859
|
-
import { jsx as
|
|
1093
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
860
1094
|
function toSlug(cat) {
|
|
861
1095
|
return cat.toLowerCase().replaceAll(/\s+/g, "-").replaceAll(/[^a-z0-9-]/g, "");
|
|
862
1096
|
}
|
|
@@ -865,11 +1099,13 @@ function ArticleDetailHero({
|
|
|
865
1099
|
categoryBasePath = "/articles/category",
|
|
866
1100
|
showDate = false,
|
|
867
1101
|
showAuthor = true,
|
|
868
|
-
authors = []
|
|
1102
|
+
authors = [],
|
|
1103
|
+
config
|
|
869
1104
|
}) {
|
|
1105
|
+
var _a;
|
|
870
1106
|
const showConfiguredAuthors = showAuthor && authors.length > 0;
|
|
871
1107
|
const showLegacyAuthor = showAuthor && authors.length === 0 && article.author.trim().length > 0;
|
|
872
|
-
return /* @__PURE__ */
|
|
1108
|
+
return /* @__PURE__ */ jsxs13(
|
|
873
1109
|
"section",
|
|
874
1110
|
{
|
|
875
1111
|
style: {
|
|
@@ -881,8 +1117,8 @@ function ArticleDetailHero({
|
|
|
881
1117
|
overflow: "hidden"
|
|
882
1118
|
},
|
|
883
1119
|
children: [
|
|
884
|
-
/* @__PURE__ */
|
|
885
|
-
|
|
1120
|
+
/* @__PURE__ */ jsx13(
|
|
1121
|
+
Image5,
|
|
886
1122
|
{
|
|
887
1123
|
src: article.featuredImage,
|
|
888
1124
|
alt: article.title,
|
|
@@ -893,7 +1129,7 @@ function ArticleDetailHero({
|
|
|
893
1129
|
priority: true
|
|
894
1130
|
}
|
|
895
1131
|
),
|
|
896
|
-
/* @__PURE__ */
|
|
1132
|
+
/* @__PURE__ */ jsx13(
|
|
897
1133
|
"div",
|
|
898
1134
|
{
|
|
899
1135
|
style: {
|
|
@@ -903,7 +1139,7 @@ function ArticleDetailHero({
|
|
|
903
1139
|
}
|
|
904
1140
|
}
|
|
905
1141
|
),
|
|
906
|
-
/* @__PURE__ */
|
|
1142
|
+
/* @__PURE__ */ jsxs13(
|
|
907
1143
|
"div",
|
|
908
1144
|
{
|
|
909
1145
|
style: {
|
|
@@ -917,7 +1153,7 @@ function ArticleDetailHero({
|
|
|
917
1153
|
width: "100%"
|
|
918
1154
|
},
|
|
919
1155
|
children: [
|
|
920
|
-
article.categories && article.categories.length > 0 && /* @__PURE__ */
|
|
1156
|
+
article.categories && article.categories.length > 0 && /* @__PURE__ */ jsx13(
|
|
921
1157
|
"div",
|
|
922
1158
|
{
|
|
923
1159
|
style: {
|
|
@@ -928,15 +1164,15 @@ function ArticleDetailHero({
|
|
|
928
1164
|
marginBottom: "1rem"
|
|
929
1165
|
},
|
|
930
1166
|
children: article.categories.slice(0, 4).map(
|
|
931
|
-
(cat) => categoryBasePath ? /* @__PURE__ */
|
|
932
|
-
|
|
1167
|
+
(cat) => categoryBasePath ? /* @__PURE__ */ jsx13(
|
|
1168
|
+
Link8,
|
|
933
1169
|
{
|
|
934
1170
|
href: `${categoryBasePath}/${toSlug(cat)}`,
|
|
935
1171
|
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
1172
|
children: cat
|
|
937
1173
|
},
|
|
938
1174
|
cat
|
|
939
|
-
) : /* @__PURE__ */
|
|
1175
|
+
) : /* @__PURE__ */ jsx13(
|
|
940
1176
|
"span",
|
|
941
1177
|
{
|
|
942
1178
|
className: "inline-block bg-white/20 text-white text-sm font-medium px-3 py-1 rounded-full",
|
|
@@ -947,8 +1183,15 @@ function ArticleDetailHero({
|
|
|
947
1183
|
)
|
|
948
1184
|
}
|
|
949
1185
|
),
|
|
950
|
-
/* @__PURE__ */
|
|
951
|
-
|
|
1186
|
+
/* @__PURE__ */ jsx13(
|
|
1187
|
+
"h1",
|
|
1188
|
+
{
|
|
1189
|
+
className: "text-4xl md:text-5xl font-bold mb-4",
|
|
1190
|
+
style: { fontFamily: (_a = config == null ? void 0 : config.theme) == null ? void 0 : _a.headerFontFamily },
|
|
1191
|
+
children: article.title
|
|
1192
|
+
}
|
|
1193
|
+
),
|
|
1194
|
+
/* @__PURE__ */ jsxs13(
|
|
952
1195
|
"div",
|
|
953
1196
|
{
|
|
954
1197
|
style: {
|
|
@@ -960,23 +1203,23 @@ function ArticleDetailHero({
|
|
|
960
1203
|
color: "rgba(255,255,255,0.8)"
|
|
961
1204
|
},
|
|
962
1205
|
children: [
|
|
963
|
-
showDate && article.date && /* @__PURE__ */
|
|
964
|
-
/* @__PURE__ */
|
|
965
|
-
/* @__PURE__ */
|
|
1206
|
+
showDate && article.date && /* @__PURE__ */ jsxs13("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1207
|
+
/* @__PURE__ */ jsx13(Calendar3, { className: "h-4 w-4" }),
|
|
1208
|
+
/* @__PURE__ */ jsx13("span", { children: article.date })
|
|
966
1209
|
] }),
|
|
967
|
-
/* @__PURE__ */
|
|
968
|
-
/* @__PURE__ */
|
|
969
|
-
/* @__PURE__ */
|
|
1210
|
+
/* @__PURE__ */ jsxs13("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1211
|
+
/* @__PURE__ */ jsx13(Clock3, { className: "h-4 w-4" }),
|
|
1212
|
+
/* @__PURE__ */ jsx13("span", { children: article.readTime })
|
|
970
1213
|
] }),
|
|
971
|
-
showConfiguredAuthors && /* @__PURE__ */
|
|
972
|
-
/* @__PURE__ */
|
|
973
|
-
/* @__PURE__ */
|
|
1214
|
+
showConfiguredAuthors && /* @__PURE__ */ jsxs13("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1215
|
+
/* @__PURE__ */ jsx13(User2, { className: "h-4 w-4" }),
|
|
1216
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
974
1217
|
"By",
|
|
975
1218
|
" ",
|
|
976
|
-
authors.map((author, index) => /* @__PURE__ */
|
|
1219
|
+
authors.map((author, index) => /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
977
1220
|
index > 0 && ", ",
|
|
978
|
-
/* @__PURE__ */
|
|
979
|
-
|
|
1221
|
+
/* @__PURE__ */ jsx13(
|
|
1222
|
+
Link8,
|
|
980
1223
|
{
|
|
981
1224
|
href: `/articles/authors/${author.slug}`,
|
|
982
1225
|
className: "font-medium text-white underline-offset-4 hover:underline",
|
|
@@ -986,15 +1229,26 @@ function ArticleDetailHero({
|
|
|
986
1229
|
] }, author.slug))
|
|
987
1230
|
] })
|
|
988
1231
|
] }),
|
|
989
|
-
showLegacyAuthor && /* @__PURE__ */
|
|
990
|
-
/* @__PURE__ */
|
|
991
|
-
/* @__PURE__ */
|
|
1232
|
+
showLegacyAuthor && /* @__PURE__ */ jsxs13("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
1233
|
+
/* @__PURE__ */ jsx13(User2, { className: "h-4 w-4" }),
|
|
1234
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
992
1235
|
"By ",
|
|
993
1236
|
article.author
|
|
994
1237
|
] })
|
|
995
1238
|
] })
|
|
996
1239
|
]
|
|
997
1240
|
}
|
|
1241
|
+
),
|
|
1242
|
+
showConfiguredAuthors && authors.length === 1 && authors[0].promise && /* @__PURE__ */ jsx13(
|
|
1243
|
+
"p",
|
|
1244
|
+
{
|
|
1245
|
+
style: {
|
|
1246
|
+
marginTop: "0.75rem",
|
|
1247
|
+
fontSize: "0.9375rem",
|
|
1248
|
+
color: "rgba(255,255,255,0.85)"
|
|
1249
|
+
},
|
|
1250
|
+
children: authors[0].promise
|
|
1251
|
+
}
|
|
998
1252
|
)
|
|
999
1253
|
]
|
|
1000
1254
|
}
|
|
@@ -1005,9 +1259,9 @@ function ArticleDetailHero({
|
|
|
1005
1259
|
}
|
|
1006
1260
|
|
|
1007
1261
|
// src/CategoryArticlesPage.tsx
|
|
1008
|
-
import
|
|
1009
|
-
import
|
|
1010
|
-
import { jsx as
|
|
1262
|
+
import Image6 from "next/image";
|
|
1263
|
+
import Link9 from "next/link";
|
|
1264
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1011
1265
|
function getCategoryDescription(config, slug, categoryName) {
|
|
1012
1266
|
var _a;
|
|
1013
1267
|
const raw = (_a = config.categoryDescriptions) == null ? void 0 : _a[slug];
|
|
@@ -1049,7 +1303,14 @@ function buildCategoryBreadcrumbEntry(entry, context) {
|
|
|
1049
1303
|
}
|
|
1050
1304
|
return [{ name: context.categoryName }];
|
|
1051
1305
|
}
|
|
1052
|
-
function CategoryArticlesPage({
|
|
1306
|
+
function CategoryArticlesPage({
|
|
1307
|
+
category,
|
|
1308
|
+
articles,
|
|
1309
|
+
config,
|
|
1310
|
+
page,
|
|
1311
|
+
totalPages,
|
|
1312
|
+
totalCount
|
|
1313
|
+
}) {
|
|
1053
1314
|
var _a;
|
|
1054
1315
|
if (articles.length === 0) return null;
|
|
1055
1316
|
const categoryName = articles[0].category;
|
|
@@ -1058,8 +1319,25 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1058
1319
|
const pageSize = (_a = config.pageSize) != null ? _a : DEFAULT_PAGE_SIZE;
|
|
1059
1320
|
const breadcrumbConfig = getBreadcrumbsConfig(config);
|
|
1060
1321
|
const breadcrumbItems = buildCategoryBreadcrumbItems(config, categoryName);
|
|
1061
|
-
|
|
1062
|
-
|
|
1322
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1323
|
+
const articleCount = totalCount != null ? totalCount : articles.length;
|
|
1324
|
+
const pagination = config.listingPagination === "pages" && page !== void 0 && totalPages !== void 0 ? { page, totalPages, basePath: `/articles/category/${category}` } : void 0;
|
|
1325
|
+
return /* @__PURE__ */ jsxs14("div", { children: [
|
|
1326
|
+
/* @__PURE__ */ jsx14(
|
|
1327
|
+
CollectionPageSchema,
|
|
1328
|
+
{
|
|
1329
|
+
title: `${categoryName} | ${config.siteName}`,
|
|
1330
|
+
description: description.short,
|
|
1331
|
+
url: `${siteUrl}/articles/category/${category}`,
|
|
1332
|
+
articleCount,
|
|
1333
|
+
items: articles.slice(0, pageSize).map((article, index) => ({
|
|
1334
|
+
position: index + 1,
|
|
1335
|
+
url: `${siteUrl}/articles/${article.slug}`,
|
|
1336
|
+
name: article.title
|
|
1337
|
+
}))
|
|
1338
|
+
}
|
|
1339
|
+
),
|
|
1340
|
+
breadcrumbsAreEnabled(config) && /* @__PURE__ */ jsx14(
|
|
1063
1341
|
Breadcrumb,
|
|
1064
1342
|
{
|
|
1065
1343
|
items: breadcrumbItems,
|
|
@@ -1067,7 +1345,7 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1067
1345
|
showSchema: breadcrumbConfig.showSchema !== false
|
|
1068
1346
|
}
|
|
1069
1347
|
),
|
|
1070
|
-
/* @__PURE__ */
|
|
1348
|
+
/* @__PURE__ */ jsxs14(
|
|
1071
1349
|
"section",
|
|
1072
1350
|
{
|
|
1073
1351
|
style: {
|
|
@@ -1079,8 +1357,8 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1079
1357
|
overflow: "hidden"
|
|
1080
1358
|
},
|
|
1081
1359
|
children: [
|
|
1082
|
-
/* @__PURE__ */
|
|
1083
|
-
|
|
1360
|
+
/* @__PURE__ */ jsx14(
|
|
1361
|
+
Image6,
|
|
1084
1362
|
{
|
|
1085
1363
|
src: heroImage,
|
|
1086
1364
|
alt: categoryName,
|
|
@@ -1090,8 +1368,8 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1090
1368
|
priority: true
|
|
1091
1369
|
}
|
|
1092
1370
|
),
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1371
|
+
/* @__PURE__ */ jsx14("div", { style: { position: "absolute", inset: 0, backgroundColor: "rgba(0,0,0,0.6)" } }),
|
|
1372
|
+
/* @__PURE__ */ jsxs14(
|
|
1095
1373
|
"div",
|
|
1096
1374
|
{
|
|
1097
1375
|
style: {
|
|
@@ -1102,10 +1380,10 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1102
1380
|
padding: "0 1rem"
|
|
1103
1381
|
},
|
|
1104
1382
|
children: [
|
|
1105
|
-
/* @__PURE__ */
|
|
1106
|
-
/* @__PURE__ */
|
|
1107
|
-
description.long && /* @__PURE__ */
|
|
1108
|
-
/* @__PURE__ */
|
|
1383
|
+
/* @__PURE__ */ jsx14("p", { className: "text-sm font-semibold uppercase tracking-widest mb-3 opacity-80", children: "Category" }),
|
|
1384
|
+
/* @__PURE__ */ jsx14("h1", { className: "text-4xl md:text-5xl font-bold mb-3", children: categoryName }),
|
|
1385
|
+
description.long && /* @__PURE__ */ jsx14("p", { className: "text-lg opacity-90 max-w-2xl mx-auto mt-2", children: description.long }),
|
|
1386
|
+
/* @__PURE__ */ jsxs14("p", { className: "text-lg opacity-70 mt-2", children: [
|
|
1109
1387
|
articles.length,
|
|
1110
1388
|
" article",
|
|
1111
1389
|
articles.length === 1 ? "" : "s"
|
|
@@ -1116,150 +1394,75 @@ function CategoryArticlesPage({ category, articles, config }) {
|
|
|
1116
1394
|
]
|
|
1117
1395
|
}
|
|
1118
1396
|
),
|
|
1119
|
-
/* @__PURE__ */
|
|
1120
|
-
/* @__PURE__ */
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */
|
|
1397
|
+
/* @__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: [
|
|
1398
|
+
/* @__PURE__ */ jsxs14("div", { className: "mb-8 flex items-center justify-between", children: [
|
|
1399
|
+
/* @__PURE__ */ jsx14(Link9, { href: "/articles", className: "text-sm text-primary hover:underline", children: "\u2190 All Articles" }),
|
|
1400
|
+
/* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: description.short })
|
|
1123
1401
|
] }),
|
|
1124
|
-
/* @__PURE__ */
|
|
1402
|
+
/* @__PURE__ */ jsx14(LatestArticles, { articles, pageSize, pagination })
|
|
1125
1403
|
] }) })
|
|
1126
1404
|
] });
|
|
1127
1405
|
}
|
|
1128
1406
|
|
|
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 }) {
|
|
1407
|
+
// src/SeriesArticlesPage.tsx
|
|
1408
|
+
import Link10 from "next/link";
|
|
1409
|
+
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1410
|
+
function SeriesArticlesPage({ seriesSlug, articles, config }) {
|
|
1151
1411
|
var _a;
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1412
|
+
if (articles.length === 0) return null;
|
|
1413
|
+
const seriesName = (_a = articles[0].series) != null ? _a : seriesSlug;
|
|
1414
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1415
|
+
const seriesUrl = `${siteUrl}/articles/series/${seriesSlug}`;
|
|
1416
|
+
return /* @__PURE__ */ jsxs15("div", { children: [
|
|
1417
|
+
/* @__PURE__ */ jsx15(
|
|
1418
|
+
CollectionPageSchema,
|
|
1156
1419
|
{
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1420
|
+
title: `${seriesName} | ${config.siteName}`,
|
|
1421
|
+
description: `Follow the ${seriesName} series on ${config.siteName}.`,
|
|
1422
|
+
url: seriesUrl,
|
|
1423
|
+
articleCount: articles.length,
|
|
1424
|
+
items: articles.map((article, index) => ({
|
|
1425
|
+
position: index + 1,
|
|
1426
|
+
url: `${siteUrl}/articles/${article.slug}`,
|
|
1427
|
+
name: article.title
|
|
1428
|
+
}))
|
|
1161
1429
|
}
|
|
1162
1430
|
),
|
|
1163
|
-
/* @__PURE__ */
|
|
1164
|
-
/* @__PURE__ */
|
|
1165
|
-
/* @__PURE__ */
|
|
1166
|
-
/* @__PURE__ */
|
|
1167
|
-
|
|
1168
|
-
|
|
1431
|
+
/* @__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: [
|
|
1432
|
+
/* @__PURE__ */ jsxs15("div", { className: "mb-8 flex items-center justify-between", children: [
|
|
1433
|
+
/* @__PURE__ */ jsx15(Link10, { href: "/articles", className: "text-sm text-primary hover:underline", children: "\u2190 All Articles" }),
|
|
1434
|
+
/* @__PURE__ */ jsxs15("p", { className: "text-sm text-muted-foreground", children: [
|
|
1435
|
+
articles.length,
|
|
1436
|
+
" article",
|
|
1437
|
+
articles.length === 1 ? "" : "s",
|
|
1438
|
+
" in this series"
|
|
1169
1439
|
] })
|
|
1170
1440
|
] }),
|
|
1171
|
-
/* @__PURE__ */
|
|
1441
|
+
/* @__PURE__ */ jsx15("h1", { className: "text-3xl font-bold text-foreground mb-8", children: seriesName }),
|
|
1442
|
+
/* @__PURE__ */ jsx15(
|
|
1443
|
+
LatestArticles,
|
|
1444
|
+
{
|
|
1445
|
+
articles,
|
|
1446
|
+
pageSize: Math.max(articles.length, DEFAULT_PAGE_SIZE)
|
|
1447
|
+
}
|
|
1448
|
+
)
|
|
1172
1449
|
] }) })
|
|
1173
1450
|
] });
|
|
1174
1451
|
}
|
|
1175
1452
|
|
|
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
|
-
}
|
|
1453
|
+
// src/AuthorArticlesPage.tsx
|
|
1454
|
+
import Link11 from "next/link";
|
|
1252
1455
|
|
|
1253
1456
|
// src/AuthorDetailHero.tsx
|
|
1254
1457
|
import Image7 from "next/image";
|
|
1255
|
-
import { jsx as
|
|
1458
|
+
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1256
1459
|
function getInitials2(name) {
|
|
1257
1460
|
return name.split(" ").filter(Boolean).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
|
|
1258
1461
|
}
|
|
1259
1462
|
function AuthorDetailHero({ author, articleCount }) {
|
|
1260
1463
|
const avatar = getAuthorAvatar(author);
|
|
1261
|
-
return /* @__PURE__ */
|
|
1262
|
-
avatar ? /* @__PURE__ */
|
|
1464
|
+
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: [
|
|
1465
|
+
avatar ? /* @__PURE__ */ jsx16(
|
|
1263
1466
|
Image7,
|
|
1264
1467
|
{
|
|
1265
1468
|
src: avatar,
|
|
@@ -1269,27 +1472,303 @@ function AuthorDetailHero({ author, articleCount }) {
|
|
|
1269
1472
|
className: "h-28 w-28 rounded-full object-cover",
|
|
1270
1473
|
priority: true
|
|
1271
1474
|
}
|
|
1272
|
-
) : /* @__PURE__ */
|
|
1273
|
-
/* @__PURE__ */
|
|
1274
|
-
/* @__PURE__ */
|
|
1275
|
-
/* @__PURE__ */
|
|
1276
|
-
/* @__PURE__ */
|
|
1277
|
-
typeof articleCount === "number" && /* @__PURE__ */
|
|
1475
|
+
) : /* @__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) }),
|
|
1476
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
1477
|
+
/* @__PURE__ */ jsx16("p", { className: "mb-3 text-sm font-semibold uppercase tracking-widest text-muted-foreground", children: "Author" }),
|
|
1478
|
+
/* @__PURE__ */ jsx16("h1", { className: "text-4xl font-bold text-foreground md:text-5xl", children: author.name }),
|
|
1479
|
+
/* @__PURE__ */ jsx16("p", { className: "mx-auto mt-4 max-w-2xl text-lg text-muted-foreground", children: author.bio }),
|
|
1480
|
+
typeof articleCount === "number" && /* @__PURE__ */ jsxs16("p", { className: "mt-3 text-sm text-muted-foreground", children: [
|
|
1278
1481
|
articleCount,
|
|
1279
1482
|
" article",
|
|
1280
1483
|
articleCount === 1 ? "" : "s"
|
|
1281
1484
|
] })
|
|
1282
1485
|
] }),
|
|
1283
|
-
/* @__PURE__ */
|
|
1486
|
+
/* @__PURE__ */ jsx16(AuthorSocialLinks, { author })
|
|
1284
1487
|
] }) });
|
|
1285
1488
|
}
|
|
1286
1489
|
|
|
1490
|
+
// src/eventTracking.tsx
|
|
1491
|
+
import { useEffect as useEffect4, useRef as useRef2 } from "react";
|
|
1492
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1493
|
+
var AVERAGE_WORDS_PER_MINUTE = 200;
|
|
1494
|
+
var DEFAULT_MEANINGFUL_READ_MS = 15e3;
|
|
1495
|
+
function ArticleViewTracker({ article, config }) {
|
|
1496
|
+
const firedMeaningfulRead = useRef2(false);
|
|
1497
|
+
useEffect4(() => {
|
|
1498
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
1499
|
+
name: "article_viewed",
|
|
1500
|
+
articleSlug: article.slug,
|
|
1501
|
+
category: article.category,
|
|
1502
|
+
seriesSlug: article.seriesSlug
|
|
1503
|
+
});
|
|
1504
|
+
const estimatedMs = article.wordCount ? article.wordCount / AVERAGE_WORDS_PER_MINUTE * 6e4 * 0.5 : DEFAULT_MEANINGFUL_READ_MS;
|
|
1505
|
+
const timer = setTimeout(() => {
|
|
1506
|
+
if (firedMeaningfulRead.current) return;
|
|
1507
|
+
firedMeaningfulRead.current = true;
|
|
1508
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, { name: "meaningful_read", articleSlug: article.slug });
|
|
1509
|
+
}, estimatedMs);
|
|
1510
|
+
return () => clearTimeout(timer);
|
|
1511
|
+
}, [article.slug]);
|
|
1512
|
+
return null;
|
|
1513
|
+
}
|
|
1514
|
+
function CtaViewTracker({ ctaId, articleSlug, config, children }) {
|
|
1515
|
+
const ref = useRef2(null);
|
|
1516
|
+
const fired = useRef2(false);
|
|
1517
|
+
useEffect4(() => {
|
|
1518
|
+
const node = ref.current;
|
|
1519
|
+
if (!node) return;
|
|
1520
|
+
function fire() {
|
|
1521
|
+
if (fired.current) return;
|
|
1522
|
+
fired.current = true;
|
|
1523
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, { name: "cta_viewed", ctaId, articleSlug });
|
|
1524
|
+
}
|
|
1525
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
1526
|
+
fire();
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
const observer = new IntersectionObserver(
|
|
1530
|
+
(entries) => {
|
|
1531
|
+
if (entries.some((entry) => entry.isIntersecting)) fire();
|
|
1532
|
+
},
|
|
1533
|
+
{ threshold: 0.5 }
|
|
1534
|
+
);
|
|
1535
|
+
observer.observe(node);
|
|
1536
|
+
return () => observer.disconnect();
|
|
1537
|
+
}, [ctaId, articleSlug]);
|
|
1538
|
+
return /* @__PURE__ */ jsx17("div", { ref, children });
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
// src/AuthorArticlesPage.tsx
|
|
1542
|
+
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1543
|
+
function getPersonSchema(author, config, articleCount) {
|
|
1544
|
+
var _a, _b;
|
|
1545
|
+
return __spreadProps(__spreadValues(__spreadValues({
|
|
1546
|
+
"@context": "https://schema.org",
|
|
1547
|
+
"@type": "Person",
|
|
1548
|
+
name: author.name,
|
|
1549
|
+
description: author.bio,
|
|
1550
|
+
url: (_a = author.url) != null ? _a : getAuthorUrl(author)
|
|
1551
|
+
}, getAuthorAvatar(author, config) && { image: getAuthorAvatar(author, config) }), getAuthorSameAs(author).length > 0 && { sameAs: getAuthorSameAs(author) }), {
|
|
1552
|
+
knowsAbout: config.siteName,
|
|
1553
|
+
mainEntityOfPage: (_b = author.url) != null ? _b : `${config.siteUrl.replace(/\/$/, "")}/articles/authors/${author.slug}`,
|
|
1554
|
+
interactionStatistic: {
|
|
1555
|
+
"@type": "InteractionCounter",
|
|
1556
|
+
interactionType: "https://schema.org/WriteAction",
|
|
1557
|
+
userInteractionCount: articleCount
|
|
1558
|
+
}
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
function renderHeroSection(author, articleCount) {
|
|
1562
|
+
return /* @__PURE__ */ jsx18(AuthorDetailHero, { author, articleCount }, "hero");
|
|
1563
|
+
}
|
|
1564
|
+
function renderPromiseSection(author) {
|
|
1565
|
+
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;
|
|
1566
|
+
}
|
|
1567
|
+
function renderServesWhoSection(author) {
|
|
1568
|
+
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: [
|
|
1569
|
+
/* @__PURE__ */ jsx18("h2", { className: "mb-4 text-center text-2xl font-bold text-foreground", children: "Who I help" }),
|
|
1570
|
+
/* @__PURE__ */ jsx18("ul", { className: "grid gap-3 sm:grid-cols-2", children: author.servesWho.map((who) => /* @__PURE__ */ jsx18(
|
|
1571
|
+
"li",
|
|
1572
|
+
{
|
|
1573
|
+
className: "rounded-lg border border-border bg-card px-4 py-3 text-sm text-card-foreground",
|
|
1574
|
+
children: who
|
|
1575
|
+
},
|
|
1576
|
+
who
|
|
1577
|
+
)) })
|
|
1578
|
+
] }) }, "servesWho") : null;
|
|
1579
|
+
}
|
|
1580
|
+
function renderOriginStorySection(author) {
|
|
1581
|
+
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: [
|
|
1582
|
+
/* @__PURE__ */ jsx18("h2", { className: "mb-6 text-2xl font-bold text-foreground", children: "My story" }),
|
|
1583
|
+
/* @__PURE__ */ jsx18("div", { className: "space-y-6", children: author.originStory.map((block, blockIndex) => {
|
|
1584
|
+
var _a;
|
|
1585
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
1586
|
+
block.heading && /* @__PURE__ */ jsx18("h3", { className: "mb-2 text-lg font-semibold text-foreground", children: block.heading }),
|
|
1587
|
+
block.paragraphs.map((paragraph, paragraphIndex) => {
|
|
1588
|
+
var _a2;
|
|
1589
|
+
return /* @__PURE__ */ jsx18(
|
|
1590
|
+
"p",
|
|
1591
|
+
{
|
|
1592
|
+
className: "mb-3 text-muted-foreground",
|
|
1593
|
+
children: paragraph
|
|
1594
|
+
},
|
|
1595
|
+
`${(_a2 = block.heading) != null ? _a2 : blockIndex}-${paragraph.slice(0, 40)}-${paragraphIndex}`
|
|
1596
|
+
);
|
|
1597
|
+
})
|
|
1598
|
+
] }, (_a = block.heading) != null ? _a : blockIndex);
|
|
1599
|
+
}) })
|
|
1600
|
+
] }) }, "originStory") : null;
|
|
1601
|
+
}
|
|
1602
|
+
function renderPrinciplesSection(author) {
|
|
1603
|
+
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: [
|
|
1604
|
+
/* @__PURE__ */ jsx18("h2", { className: "mb-4 text-center text-2xl font-bold text-foreground", children: "What I believe" }),
|
|
1605
|
+
/* @__PURE__ */ jsx18("ul", { className: "space-y-3", children: author.principles.map((principle) => /* @__PURE__ */ jsx18(
|
|
1606
|
+
"li",
|
|
1607
|
+
{
|
|
1608
|
+
className: "rounded-lg border border-border bg-card px-4 py-3 text-sm text-card-foreground",
|
|
1609
|
+
children: principle
|
|
1610
|
+
},
|
|
1611
|
+
principle
|
|
1612
|
+
)) })
|
|
1613
|
+
] }) }, "principles") : null;
|
|
1614
|
+
}
|
|
1615
|
+
function renderProofSection(author) {
|
|
1616
|
+
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: [
|
|
1617
|
+
/* @__PURE__ */ jsx18("h2", { className: "mb-6 text-center text-2xl font-bold text-foreground", children: "Proof" }),
|
|
1618
|
+
/* @__PURE__ */ jsx18("div", { className: "grid gap-4 sm:grid-cols-2", children: author.proof.map((item) => {
|
|
1619
|
+
var _a, _b, _c;
|
|
1620
|
+
return /* @__PURE__ */ jsxs17(
|
|
1621
|
+
"div",
|
|
1622
|
+
{
|
|
1623
|
+
className: "rounded-lg border border-border bg-card p-4 text-card-foreground",
|
|
1624
|
+
children: [
|
|
1625
|
+
/* @__PURE__ */ jsx18("p", { className: "font-medium", children: item.claim }),
|
|
1626
|
+
(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 })
|
|
1627
|
+
]
|
|
1628
|
+
},
|
|
1629
|
+
`${item.claim}-${(_b = (_a = item.url) != null ? _a : item.source) != null ? _b : ""}`
|
|
1630
|
+
);
|
|
1631
|
+
}) })
|
|
1632
|
+
] }) }, "proof") : null;
|
|
1633
|
+
}
|
|
1634
|
+
function renderCtaSection(author, config) {
|
|
1635
|
+
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(
|
|
1636
|
+
Link11,
|
|
1637
|
+
{
|
|
1638
|
+
href: author.primaryCta.href,
|
|
1639
|
+
onClick: () => emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
1640
|
+
name: "cta_clicked",
|
|
1641
|
+
ctaId: `author-cta:${author.slug}`
|
|
1642
|
+
}),
|
|
1643
|
+
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",
|
|
1644
|
+
children: author.primaryCta.label
|
|
1645
|
+
}
|
|
1646
|
+
) }) }) }, "cta") : null;
|
|
1647
|
+
}
|
|
1648
|
+
function renderArticlesSection(author, articles, pageSize, pagination) {
|
|
1649
|
+
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: [
|
|
1650
|
+
/* @__PURE__ */ jsxs17("div", { className: "mb-8 flex items-center justify-between gap-4", children: [
|
|
1651
|
+
/* @__PURE__ */ jsx18(Link11, { href: "/articles", className: "text-sm text-primary hover:underline", children: "All Articles" }),
|
|
1652
|
+
/* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
|
|
1653
|
+
"Articles by ",
|
|
1654
|
+
author.name
|
|
1655
|
+
] })
|
|
1656
|
+
] }),
|
|
1657
|
+
/* @__PURE__ */ jsx18(LatestArticles, { articles, pageSize, pagination })
|
|
1658
|
+
] }) }, "articles");
|
|
1659
|
+
}
|
|
1660
|
+
function renderAuthorSection(section, ctx) {
|
|
1661
|
+
const { author, articleCount, articles, pageSize, pagination, customSection, config } = ctx;
|
|
1662
|
+
switch (section) {
|
|
1663
|
+
case "hero":
|
|
1664
|
+
return renderHeroSection(author, articleCount);
|
|
1665
|
+
case "promise":
|
|
1666
|
+
return renderPromiseSection(author);
|
|
1667
|
+
case "servesWho":
|
|
1668
|
+
return renderServesWhoSection(author);
|
|
1669
|
+
case "originStory":
|
|
1670
|
+
return renderOriginStorySection(author);
|
|
1671
|
+
case "principles":
|
|
1672
|
+
return renderPrinciplesSection(author);
|
|
1673
|
+
case "proof":
|
|
1674
|
+
return renderProofSection(author);
|
|
1675
|
+
case "cta":
|
|
1676
|
+
return renderCtaSection(author, config);
|
|
1677
|
+
case "articles":
|
|
1678
|
+
return renderArticlesSection(author, articles, pageSize, pagination);
|
|
1679
|
+
case "custom":
|
|
1680
|
+
return customSection != null ? customSection : null;
|
|
1681
|
+
default:
|
|
1682
|
+
return null;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
function AuthorArticlesPage({
|
|
1686
|
+
author,
|
|
1687
|
+
articles,
|
|
1688
|
+
config,
|
|
1689
|
+
page,
|
|
1690
|
+
totalPages,
|
|
1691
|
+
totalCount,
|
|
1692
|
+
sections,
|
|
1693
|
+
customSection
|
|
1694
|
+
}) {
|
|
1695
|
+
var _a, _b;
|
|
1696
|
+
const pageSize = (_a = config.pageSize) != null ? _a : DEFAULT_PAGE_SIZE;
|
|
1697
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1698
|
+
const articleCount = totalCount != null ? totalCount : articles.length;
|
|
1699
|
+
const pagination = config.listingPagination === "pages" && page !== void 0 && totalPages !== void 0 ? { page, totalPages, basePath: `/articles/authors/${author.slug}` } : void 0;
|
|
1700
|
+
const schemas = /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
1701
|
+
/* @__PURE__ */ jsx18(
|
|
1702
|
+
"script",
|
|
1703
|
+
{
|
|
1704
|
+
type: "application/ld+json",
|
|
1705
|
+
dangerouslySetInnerHTML: {
|
|
1706
|
+
__html: JSON.stringify(getPersonSchema(author, config, articleCount))
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
),
|
|
1710
|
+
/* @__PURE__ */ jsx18(
|
|
1711
|
+
CollectionPageSchema,
|
|
1712
|
+
{
|
|
1713
|
+
title: `${author.name} | ${config.siteName}`,
|
|
1714
|
+
description: `Articles by ${author.name} on ${config.siteName}.`,
|
|
1715
|
+
url: (_b = author.url) != null ? _b : `${siteUrl}/articles/authors/${author.slug}`,
|
|
1716
|
+
articleCount,
|
|
1717
|
+
items: articles.slice(0, pageSize).map((article, index) => ({
|
|
1718
|
+
position: index + 1,
|
|
1719
|
+
url: `${siteUrl}/articles/${article.slug}`,
|
|
1720
|
+
name: article.title
|
|
1721
|
+
}))
|
|
1722
|
+
}
|
|
1723
|
+
)
|
|
1724
|
+
] });
|
|
1725
|
+
if (!sections) {
|
|
1726
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
1727
|
+
schemas,
|
|
1728
|
+
/* @__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: [
|
|
1729
|
+
/* @__PURE__ */ jsxs17("div", { className: "mb-8 flex items-center justify-between gap-4", children: [
|
|
1730
|
+
/* @__PURE__ */ jsx18(Link11, { href: "/articles", className: "text-sm text-primary hover:underline", children: "All Articles" }),
|
|
1731
|
+
/* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
|
|
1732
|
+
"Articles by ",
|
|
1733
|
+
author.name
|
|
1734
|
+
] })
|
|
1735
|
+
] }),
|
|
1736
|
+
/* @__PURE__ */ jsx18(LatestArticles, { articles, pageSize, pagination })
|
|
1737
|
+
] }) })
|
|
1738
|
+
] });
|
|
1739
|
+
}
|
|
1740
|
+
const sectionCtx = {
|
|
1741
|
+
author,
|
|
1742
|
+
articleCount,
|
|
1743
|
+
articles,
|
|
1744
|
+
pageSize,
|
|
1745
|
+
pagination,
|
|
1746
|
+
customSection,
|
|
1747
|
+
config
|
|
1748
|
+
};
|
|
1749
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
1750
|
+
schemas,
|
|
1751
|
+
sections.map((section) => renderAuthorSection(section, sectionCtx))
|
|
1752
|
+
] });
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1287
1755
|
// src/ArticleSocialShare.tsx
|
|
1288
1756
|
import { useState as useState4 } from "react";
|
|
1289
1757
|
import { Share2, Copy, Check, Mail as Mail2, MessageCircle as MessageCircle2, Users, FileText } from "lucide-react";
|
|
1290
|
-
import { jsx as
|
|
1291
|
-
function ArticleSocialShare({
|
|
1758
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1759
|
+
function ArticleSocialShare({
|
|
1760
|
+
title,
|
|
1761
|
+
url,
|
|
1762
|
+
excerpt,
|
|
1763
|
+
shareMessage,
|
|
1764
|
+
config,
|
|
1765
|
+
articleSlug
|
|
1766
|
+
}) {
|
|
1292
1767
|
const [copied, setCopied] = useState4(false);
|
|
1768
|
+
function trackShare(channel) {
|
|
1769
|
+
if (!articleSlug) return;
|
|
1770
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, { name: "shared", articleSlug, channel });
|
|
1771
|
+
}
|
|
1293
1772
|
const encodedTitle = encodeURIComponent(title);
|
|
1294
1773
|
const encodedUrl = encodeURIComponent(url);
|
|
1295
1774
|
const encodedExcerpt = encodeURIComponent(excerpt || "");
|
|
@@ -1306,102 +1785,211 @@ function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
|
|
|
1306
1785
|
try {
|
|
1307
1786
|
yield navigator.clipboard.writeText(url);
|
|
1308
1787
|
setCopied(true);
|
|
1788
|
+
trackShare("copy-link");
|
|
1309
1789
|
setTimeout(() => setCopied(false), 2e3);
|
|
1310
1790
|
} catch (e) {
|
|
1311
1791
|
}
|
|
1312
1792
|
});
|
|
1313
|
-
const openShareWindow = (shareUrl) => {
|
|
1793
|
+
const openShareWindow = (shareUrl, channel) => {
|
|
1794
|
+
trackShare(channel);
|
|
1314
1795
|
globalThis.open(shareUrl, "_blank", "width=600,height=400,scrollbars=yes,resizable=yes");
|
|
1315
1796
|
};
|
|
1316
1797
|
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__ */
|
|
1798
|
+
return /* @__PURE__ */ jsxs18("div", { className: "border-t border-border pt-8 mt-8", children: [
|
|
1799
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 mb-4", children: [
|
|
1800
|
+
/* @__PURE__ */ jsx19(Share2, { className: "h-5 w-5 text-muted-foreground" }),
|
|
1801
|
+
/* @__PURE__ */ jsx19("h3", { className: "text-lg font-semibold text-foreground", children: "Share this article" })
|
|
1321
1802
|
] }),
|
|
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
|
-
|
|
1803
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap gap-2", children: [
|
|
1804
|
+
/* @__PURE__ */ jsxs18(
|
|
1805
|
+
"button",
|
|
1806
|
+
{
|
|
1807
|
+
type: "button",
|
|
1808
|
+
className: btnClass,
|
|
1809
|
+
onClick: () => openShareWindow(shareLinks.linkedin, "linkedin"),
|
|
1810
|
+
children: [
|
|
1811
|
+
/* @__PURE__ */ jsx19(Users, { className: "h-4 w-4" }),
|
|
1812
|
+
"LinkedIn"
|
|
1813
|
+
]
|
|
1814
|
+
}
|
|
1815
|
+
),
|
|
1816
|
+
/* @__PURE__ */ jsxs18(
|
|
1817
|
+
"button",
|
|
1818
|
+
{
|
|
1819
|
+
type: "button",
|
|
1820
|
+
className: btnClass,
|
|
1821
|
+
onClick: () => openShareWindow(shareLinks.facebook, "facebook"),
|
|
1822
|
+
children: [
|
|
1823
|
+
/* @__PURE__ */ jsx19("span", { className: "text-xs font-bold", children: "f" }),
|
|
1824
|
+
" Facebook"
|
|
1825
|
+
]
|
|
1826
|
+
}
|
|
1827
|
+
),
|
|
1828
|
+
/* @__PURE__ */ jsxs18(
|
|
1829
|
+
"button",
|
|
1830
|
+
{
|
|
1831
|
+
type: "button",
|
|
1832
|
+
className: btnClass,
|
|
1833
|
+
onClick: () => openShareWindow(shareLinks.twitter, "twitter"),
|
|
1834
|
+
children: [
|
|
1835
|
+
/* @__PURE__ */ jsx19(MessageCircle2, { className: "h-4 w-4" }),
|
|
1836
|
+
"Twitter"
|
|
1837
|
+
]
|
|
1838
|
+
}
|
|
1839
|
+
),
|
|
1840
|
+
/* @__PURE__ */ jsxs18(
|
|
1841
|
+
"button",
|
|
1842
|
+
{
|
|
1843
|
+
type: "button",
|
|
1844
|
+
className: btnClass,
|
|
1845
|
+
onClick: () => openShareWindow(shareLinks.reddit, "reddit"),
|
|
1846
|
+
children: [
|
|
1847
|
+
/* @__PURE__ */ jsx19(FileText, { className: "h-4 w-4" }),
|
|
1848
|
+
"Reddit"
|
|
1849
|
+
]
|
|
1850
|
+
}
|
|
1851
|
+
),
|
|
1852
|
+
/* @__PURE__ */ jsxs18(
|
|
1853
|
+
"button",
|
|
1854
|
+
{
|
|
1855
|
+
type: "button",
|
|
1856
|
+
className: btnClass,
|
|
1857
|
+
onClick: () => openShareWindow(shareLinks.whatsapp, "whatsapp"),
|
|
1858
|
+
children: [
|
|
1859
|
+
/* @__PURE__ */ jsx19(MessageCircle2, { className: "h-4 w-4" }),
|
|
1860
|
+
"WhatsApp"
|
|
1861
|
+
]
|
|
1862
|
+
}
|
|
1863
|
+
),
|
|
1864
|
+
/* @__PURE__ */ jsxs18(
|
|
1865
|
+
"button",
|
|
1866
|
+
{
|
|
1867
|
+
type: "button",
|
|
1868
|
+
className: btnClass,
|
|
1869
|
+
onClick: () => openShareWindow(shareLinks.telegram, "telegram"),
|
|
1870
|
+
children: [
|
|
1871
|
+
/* @__PURE__ */ jsx19(MessageCircle2, { className: "h-4 w-4" }),
|
|
1872
|
+
"Telegram"
|
|
1873
|
+
]
|
|
1874
|
+
}
|
|
1875
|
+
),
|
|
1876
|
+
/* @__PURE__ */ jsxs18("a", { className: btnClass, href: shareLinks.email, onClick: () => trackShare("email"), children: [
|
|
1877
|
+
/* @__PURE__ */ jsx19(Mail2, { className: "h-4 w-4" }),
|
|
1349
1878
|
"Email"
|
|
1350
1879
|
] }),
|
|
1351
|
-
/* @__PURE__ */
|
|
1352
|
-
copied ? /* @__PURE__ */
|
|
1880
|
+
/* @__PURE__ */ jsxs18("button", { type: "button", className: btnClass, onClick: copyToClipboard, children: [
|
|
1881
|
+
copied ? /* @__PURE__ */ jsx19(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx19(Copy, { className: "h-4 w-4" }),
|
|
1353
1882
|
copied ? "Copied!" : "Copy Link"
|
|
1354
1883
|
] })
|
|
1355
1884
|
] }),
|
|
1356
|
-
shareMessage && /* @__PURE__ */
|
|
1885
|
+
shareMessage && /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground mt-3", children: shareMessage })
|
|
1357
1886
|
] });
|
|
1358
1887
|
}
|
|
1359
1888
|
|
|
1360
1889
|
// src/ArticleNavigation.tsx
|
|
1361
|
-
import
|
|
1362
|
-
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
1363
|
-
import { jsx as
|
|
1890
|
+
import Link12 from "next/link";
|
|
1891
|
+
import { ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight2 } from "lucide-react";
|
|
1892
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1364
1893
|
function truncateTitle(title, maxLength = 60) {
|
|
1365
1894
|
return title.length > maxLength ? `${title.substring(0, maxLength)}...` : title;
|
|
1366
1895
|
}
|
|
1367
|
-
function ArticleNavigation({
|
|
1896
|
+
function ArticleNavigation({
|
|
1897
|
+
previous,
|
|
1898
|
+
next,
|
|
1899
|
+
basePath,
|
|
1900
|
+
fromSlug,
|
|
1901
|
+
pathKey,
|
|
1902
|
+
config
|
|
1903
|
+
}) {
|
|
1368
1904
|
if (!previous && !next) return null;
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1905
|
+
function emitStep(toSlug2, direction) {
|
|
1906
|
+
if (!pathKey || !fromSlug) return;
|
|
1907
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
1908
|
+
name: "path_step_advanced",
|
|
1909
|
+
pathKey,
|
|
1910
|
+
fromSlug,
|
|
1911
|
+
toSlug: toSlug2,
|
|
1912
|
+
direction
|
|
1913
|
+
});
|
|
1914
|
+
}
|
|
1915
|
+
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: [
|
|
1916
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: previous && /* @__PURE__ */ jsxs19(
|
|
1917
|
+
Link12,
|
|
1372
1918
|
{
|
|
1373
1919
|
href: `${basePath}/${previous.slug}`,
|
|
1920
|
+
onClick: () => emitStep(previous.slug, "previous"),
|
|
1374
1921
|
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
1922
|
children: [
|
|
1376
|
-
/* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1378
|
-
/* @__PURE__ */
|
|
1379
|
-
/* @__PURE__ */
|
|
1923
|
+
/* @__PURE__ */ jsx20(ChevronLeft2, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" }),
|
|
1924
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0 flex-1", children: [
|
|
1925
|
+
/* @__PURE__ */ jsx20("div", { className: "text-sm text-muted-foreground mb-1", children: "Previous Article" }),
|
|
1926
|
+
/* @__PURE__ */ jsx20("div", { className: "font-medium text-foreground truncate", title: previous.title, children: truncateTitle(previous.title) })
|
|
1380
1927
|
] })
|
|
1381
1928
|
]
|
|
1382
1929
|
}
|
|
1383
1930
|
) }),
|
|
1384
|
-
/* @__PURE__ */
|
|
1385
|
-
|
|
1931
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: next && /* @__PURE__ */ jsxs19(
|
|
1932
|
+
Link12,
|
|
1386
1933
|
{
|
|
1387
1934
|
href: `${basePath}/${next.slug}`,
|
|
1935
|
+
onClick: () => emitStep(next.slug, "next"),
|
|
1388
1936
|
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
1937
|
children: [
|
|
1390
|
-
/* @__PURE__ */
|
|
1391
|
-
/* @__PURE__ */
|
|
1392
|
-
/* @__PURE__ */
|
|
1938
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0 flex-1 text-right", children: [
|
|
1939
|
+
/* @__PURE__ */ jsx20("div", { className: "text-sm text-muted-foreground mb-1", children: "Next Article" }),
|
|
1940
|
+
/* @__PURE__ */ jsx20("div", { className: "font-medium text-foreground truncate", title: next.title, children: truncateTitle(next.title) })
|
|
1393
1941
|
] }),
|
|
1394
|
-
/* @__PURE__ */
|
|
1942
|
+
/* @__PURE__ */ jsx20(ChevronRight2, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" })
|
|
1395
1943
|
]
|
|
1396
1944
|
}
|
|
1397
1945
|
) })
|
|
1398
1946
|
] }) });
|
|
1399
1947
|
}
|
|
1400
1948
|
|
|
1949
|
+
// src/RelatedArticlesSection.tsx
|
|
1950
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1951
|
+
function RelatedArticlesSection({
|
|
1952
|
+
articles,
|
|
1953
|
+
category,
|
|
1954
|
+
heading,
|
|
1955
|
+
config,
|
|
1956
|
+
fromSlug,
|
|
1957
|
+
source = "category"
|
|
1958
|
+
}) {
|
|
1959
|
+
var _a;
|
|
1960
|
+
if (articles.length === 0) return null;
|
|
1961
|
+
return /* @__PURE__ */ jsxs20("section", { className: "mt-12 pt-8 border-t border-border", "aria-label": "Related articles", children: [
|
|
1962
|
+
/* @__PURE__ */ jsx21(
|
|
1963
|
+
"h2",
|
|
1964
|
+
{
|
|
1965
|
+
className: "text-xl font-semibold text-foreground mb-6",
|
|
1966
|
+
style: { fontFamily: (_a = config == null ? void 0 : config.theme) == null ? void 0 : _a.headerFontFamily },
|
|
1967
|
+
children: heading != null ? heading : `More in ${category}`
|
|
1968
|
+
}
|
|
1969
|
+
),
|
|
1970
|
+
/* @__PURE__ */ jsx21("div", { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: articles.map((article) => /* @__PURE__ */ jsx21(
|
|
1971
|
+
"div",
|
|
1972
|
+
{
|
|
1973
|
+
onClickCapture: () => {
|
|
1974
|
+
if (!fromSlug) return;
|
|
1975
|
+
emitArticleEvent(config == null ? void 0 : config.onEvent, {
|
|
1976
|
+
name: "related_article_clicked",
|
|
1977
|
+
fromSlug,
|
|
1978
|
+
toSlug: article.slug,
|
|
1979
|
+
source
|
|
1980
|
+
});
|
|
1981
|
+
},
|
|
1982
|
+
children: /* @__PURE__ */ jsx21(ArticleCard, { article, config })
|
|
1983
|
+
},
|
|
1984
|
+
article.slug
|
|
1985
|
+
)) })
|
|
1986
|
+
] });
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1401
1989
|
// src/ArticleBackLink.tsx
|
|
1402
|
-
import
|
|
1990
|
+
import Link13 from "next/link";
|
|
1403
1991
|
import { ArrowLeft } from "lucide-react";
|
|
1404
|
-
import { jsx as
|
|
1992
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1405
1993
|
function ArticleBackLink({
|
|
1406
1994
|
config,
|
|
1407
1995
|
href = "/articles",
|
|
@@ -1409,13 +1997,13 @@ function ArticleBackLink({
|
|
|
1409
1997
|
className
|
|
1410
1998
|
}) {
|
|
1411
1999
|
if (config.showBackToArticles === false) return null;
|
|
1412
|
-
return /* @__PURE__ */
|
|
1413
|
-
|
|
2000
|
+
return /* @__PURE__ */ jsxs21(
|
|
2001
|
+
Link13,
|
|
1414
2002
|
{
|
|
1415
2003
|
href,
|
|
1416
2004
|
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
2005
|
children: [
|
|
1418
|
-
/* @__PURE__ */
|
|
2006
|
+
/* @__PURE__ */ jsx22(ArrowLeft, { className: "h-4 w-4" }),
|
|
1419
2007
|
label
|
|
1420
2008
|
]
|
|
1421
2009
|
}
|
|
@@ -1423,17 +2011,17 @@ function ArticleBackLink({
|
|
|
1423
2011
|
}
|
|
1424
2012
|
|
|
1425
2013
|
// src/ArticleTOC.tsx
|
|
1426
|
-
import { jsx as
|
|
2014
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1427
2015
|
function ArticleTOC({ toc, className }) {
|
|
1428
2016
|
if (!toc.length) return null;
|
|
1429
|
-
return /* @__PURE__ */
|
|
2017
|
+
return /* @__PURE__ */ jsxs22(
|
|
1430
2018
|
"nav",
|
|
1431
2019
|
{
|
|
1432
2020
|
"aria-label": "Table of contents",
|
|
1433
2021
|
className: `mb-8 rounded-lg border border-border bg-muted/40 px-6 py-4 ${className != null ? className : ""}`,
|
|
1434
2022
|
children: [
|
|
1435
|
-
/* @__PURE__ */
|
|
1436
|
-
/* @__PURE__ */
|
|
2023
|
+
/* @__PURE__ */ jsx23("p", { className: "mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: "On this page" }),
|
|
2024
|
+
/* @__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
2025
|
"a",
|
|
1438
2026
|
{
|
|
1439
2027
|
href: `#${item.id}`,
|
|
@@ -1447,35 +2035,35 @@ function ArticleTOC({ toc, className }) {
|
|
|
1447
2035
|
}
|
|
1448
2036
|
|
|
1449
2037
|
// src/ScrollToTop.tsx
|
|
1450
|
-
import { useEffect as
|
|
2038
|
+
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
1451
2039
|
import { ArrowUp } from "lucide-react";
|
|
1452
|
-
import { jsx as
|
|
2040
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1453
2041
|
function ScrollToTop() {
|
|
1454
2042
|
const [visible, setVisible] = useState5(false);
|
|
1455
|
-
|
|
2043
|
+
useEffect5(() => {
|
|
1456
2044
|
const onScroll = () => setVisible(globalThis.scrollY > 300);
|
|
1457
2045
|
globalThis.addEventListener("scroll", onScroll, { passive: true });
|
|
1458
2046
|
return () => globalThis.removeEventListener("scroll", onScroll);
|
|
1459
2047
|
}, []);
|
|
1460
2048
|
if (!visible) return null;
|
|
1461
|
-
return /* @__PURE__ */
|
|
2049
|
+
return /* @__PURE__ */ jsx24(
|
|
1462
2050
|
"button",
|
|
1463
2051
|
{
|
|
1464
2052
|
"aria-label": "Scroll to top",
|
|
1465
2053
|
onClick: () => globalThis.scrollTo({ top: 0, behavior: "smooth" }),
|
|
1466
2054
|
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__ */
|
|
2055
|
+
children: /* @__PURE__ */ jsx24(ArrowUp, { className: "h-5 w-5" })
|
|
1468
2056
|
}
|
|
1469
2057
|
);
|
|
1470
2058
|
}
|
|
1471
2059
|
|
|
1472
2060
|
// src/CommentsSection.tsx
|
|
1473
2061
|
import { useSession, signIn } from "next-auth/react";
|
|
1474
|
-
import { useCallback as useCallback2, useEffect as
|
|
2062
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useState as useState8 } from "react";
|
|
1475
2063
|
|
|
1476
2064
|
// src/CommentForm.tsx
|
|
1477
2065
|
import { useState as useState6 } from "react";
|
|
1478
|
-
import { jsx as
|
|
2066
|
+
import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1479
2067
|
var MAX_LENGTH = 2e3;
|
|
1480
2068
|
var WARN_THRESHOLD = 1800;
|
|
1481
2069
|
function submitLabel(submitting, parentId) {
|
|
@@ -1514,8 +2102,8 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1514
2102
|
}
|
|
1515
2103
|
});
|
|
1516
2104
|
}
|
|
1517
|
-
return /* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
2105
|
+
return /* @__PURE__ */ jsxs23("form", { onSubmit: handleSubmit, className: "space-y-2", children: [
|
|
2106
|
+
/* @__PURE__ */ jsx25(
|
|
1519
2107
|
"textarea",
|
|
1520
2108
|
{
|
|
1521
2109
|
value: body,
|
|
@@ -1528,13 +2116,13 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1528
2116
|
"aria-label": parentId ? "Reply text" : "Comment text"
|
|
1529
2117
|
}
|
|
1530
2118
|
),
|
|
1531
|
-
remaining <= MAX_LENGTH - WARN_THRESHOLD && /* @__PURE__ */
|
|
2119
|
+
remaining <= MAX_LENGTH - WARN_THRESHOLD && /* @__PURE__ */ jsxs23("p", { className: `text-xs ${remaining < 0 ? "text-destructive" : "text-muted-foreground"}`, children: [
|
|
1532
2120
|
remaining,
|
|
1533
2121
|
" characters remaining"
|
|
1534
2122
|
] }),
|
|
1535
|
-
error && /* @__PURE__ */
|
|
1536
|
-
/* @__PURE__ */
|
|
1537
|
-
/* @__PURE__ */
|
|
2123
|
+
error && /* @__PURE__ */ jsx25("p", { className: "text-xs text-destructive", children: error }),
|
|
2124
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex gap-2", children: [
|
|
2125
|
+
/* @__PURE__ */ jsx25(
|
|
1538
2126
|
"button",
|
|
1539
2127
|
{
|
|
1540
2128
|
type: "submit",
|
|
@@ -1543,7 +2131,7 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1543
2131
|
children: submitLabel(submitting, parentId)
|
|
1544
2132
|
}
|
|
1545
2133
|
),
|
|
1546
|
-
onCancel && /* @__PURE__ */
|
|
2134
|
+
onCancel && /* @__PURE__ */ jsx25(
|
|
1547
2135
|
"button",
|
|
1548
2136
|
{
|
|
1549
2137
|
type: "button",
|
|
@@ -1558,7 +2146,7 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
|
|
|
1558
2146
|
|
|
1559
2147
|
// src/CommentItem.tsx
|
|
1560
2148
|
import { useState as useState7 } from "react";
|
|
1561
|
-
import { Fragment as
|
|
2149
|
+
import { Fragment as Fragment5, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1562
2150
|
function relativeTime(iso) {
|
|
1563
2151
|
const diff = Date.now() - new Date(iso).getTime();
|
|
1564
2152
|
const minutes = Math.floor(diff / 6e4);
|
|
@@ -1596,15 +2184,15 @@ function CommentItem({
|
|
|
1596
2184
|
}
|
|
1597
2185
|
});
|
|
1598
2186
|
}
|
|
1599
|
-
return /* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
/* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
/* @__PURE__ */
|
|
2187
|
+
return /* @__PURE__ */ jsxs24("div", { className: `${isReply ? "ml-8 border-l-2 border-border pl-4" : ""}`, children: [
|
|
2188
|
+
/* @__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: [
|
|
2189
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2190
|
+
/* @__PURE__ */ jsx26("span", { className: "text-sm font-medium text-foreground", children: comment.authorName }),
|
|
2191
|
+
/* @__PURE__ */ jsx26("span", { className: "text-xs text-muted-foreground", children: relativeTime(comment.createdAt) })
|
|
1604
2192
|
] }),
|
|
1605
|
-
/* @__PURE__ */
|
|
1606
|
-
/* @__PURE__ */
|
|
1607
|
-
canReply && /* @__PURE__ */
|
|
2193
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm text-foreground whitespace-pre-wrap break-words", children: comment.body }),
|
|
2194
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex gap-3 pt-1", children: [
|
|
2195
|
+
canReply && /* @__PURE__ */ jsx26(
|
|
1608
2196
|
"button",
|
|
1609
2197
|
{
|
|
1610
2198
|
onClick: () => setShowReplyForm((v) => !v),
|
|
@@ -1612,7 +2200,7 @@ function CommentItem({
|
|
|
1612
2200
|
children: showReplyForm ? "Cancel" : "Reply"
|
|
1613
2201
|
}
|
|
1614
2202
|
),
|
|
1615
|
-
canDelete && /* @__PURE__ */
|
|
2203
|
+
canDelete && /* @__PURE__ */ jsx26(
|
|
1616
2204
|
"button",
|
|
1617
2205
|
{
|
|
1618
2206
|
onClick: handleDelete,
|
|
@@ -1623,7 +2211,7 @@ function CommentItem({
|
|
|
1623
2211
|
)
|
|
1624
2212
|
] })
|
|
1625
2213
|
] }) }),
|
|
1626
|
-
showReplyForm && /* @__PURE__ */
|
|
2214
|
+
showReplyForm && /* @__PURE__ */ jsx26("div", { className: "mt-2 ml-2", children: /* @__PURE__ */ jsx26(
|
|
1627
2215
|
CommentForm,
|
|
1628
2216
|
{
|
|
1629
2217
|
articleSlug,
|
|
@@ -1635,7 +2223,7 @@ function CommentItem({
|
|
|
1635
2223
|
onCancel: () => setShowReplyForm(false)
|
|
1636
2224
|
}
|
|
1637
2225
|
) }),
|
|
1638
|
-
replies.length > 0 && /* @__PURE__ */
|
|
2226
|
+
replies.length > 0 && /* @__PURE__ */ jsx26("div", { className: "mt-2 space-y-2", children: replies.map((reply) => /* @__PURE__ */ jsx26(
|
|
1639
2227
|
CommentItem,
|
|
1640
2228
|
{
|
|
1641
2229
|
comment: __spreadProps(__spreadValues({}, reply), { replies: [] }),
|
|
@@ -1650,7 +2238,7 @@ function CommentItem({
|
|
|
1650
2238
|
}
|
|
1651
2239
|
|
|
1652
2240
|
// src/CommentThread.tsx
|
|
1653
|
-
import { jsx as
|
|
2241
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
1654
2242
|
function CommentThread({
|
|
1655
2243
|
comments,
|
|
1656
2244
|
articleSlug,
|
|
@@ -1658,9 +2246,9 @@ function CommentThread({
|
|
|
1658
2246
|
onRefresh
|
|
1659
2247
|
}) {
|
|
1660
2248
|
if (comments.length === 0) {
|
|
1661
|
-
return /* @__PURE__ */
|
|
2249
|
+
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
2250
|
}
|
|
1663
|
-
return /* @__PURE__ */
|
|
2251
|
+
return /* @__PURE__ */ jsx27("div", { className: "space-y-4", children: comments.map((comment) => /* @__PURE__ */ jsx27(
|
|
1664
2252
|
CommentItem,
|
|
1665
2253
|
{
|
|
1666
2254
|
comment,
|
|
@@ -1673,7 +2261,7 @@ function CommentThread({
|
|
|
1673
2261
|
}
|
|
1674
2262
|
|
|
1675
2263
|
// src/CommentsSection.tsx
|
|
1676
|
-
import { jsx as
|
|
2264
|
+
import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1677
2265
|
function CommentsSection({ articleSlug, config }) {
|
|
1678
2266
|
var _a, _b, _c, _d, _e, _f;
|
|
1679
2267
|
const { data: session, status } = useSession();
|
|
@@ -1697,7 +2285,7 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1697
2285
|
setLoading(false);
|
|
1698
2286
|
}
|
|
1699
2287
|
}), [articleSlug]);
|
|
1700
|
-
|
|
2288
|
+
useEffect6(() => {
|
|
1701
2289
|
if (enabled) {
|
|
1702
2290
|
fetchComments().catch(() => void 0);
|
|
1703
2291
|
}
|
|
@@ -1705,10 +2293,10 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1705
2293
|
if (!enabled) return null;
|
|
1706
2294
|
const count = comments.length;
|
|
1707
2295
|
const label = count === 1 ? "1 comment" : `${count} comments`;
|
|
1708
|
-
return /* @__PURE__ */
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
status === "authenticated" ? /* @__PURE__ */
|
|
1711
|
-
/* @__PURE__ */
|
|
2296
|
+
return /* @__PURE__ */ jsxs25("section", { "aria-label": "Comments", className: "mt-12 pt-8 border-t border-border space-y-6", children: [
|
|
2297
|
+
/* @__PURE__ */ jsx28("h2", { className: "text-xl font-semibold text-foreground", children: loading ? "Comments" : label }),
|
|
2298
|
+
status === "authenticated" ? /* @__PURE__ */ jsx28(CommentForm, { articleSlug, onSuccess: fetchComments }) : /* @__PURE__ */ jsxs25("p", { className: "text-sm text-muted-foreground", children: [
|
|
2299
|
+
/* @__PURE__ */ jsx28(
|
|
1712
2300
|
"button",
|
|
1713
2301
|
{
|
|
1714
2302
|
onClick: () => signIn(),
|
|
@@ -1719,8 +2307,8 @@ function CommentsSection({ articleSlug, config }) {
|
|
|
1719
2307
|
" ",
|
|
1720
2308
|
"to join the discussion."
|
|
1721
2309
|
] }),
|
|
1722
|
-
fetchError && /* @__PURE__ */
|
|
1723
|
-
loading ? /* @__PURE__ */
|
|
2310
|
+
fetchError && /* @__PURE__ */ jsx28("p", { className: "text-sm text-destructive", children: fetchError }),
|
|
2311
|
+
loading ? /* @__PURE__ */ jsx28("p", { className: "text-sm text-muted-foreground", children: "Loading comments\u2026" }) : /* @__PURE__ */ jsx28(
|
|
1724
2312
|
CommentThread,
|
|
1725
2313
|
{
|
|
1726
2314
|
comments,
|
|
@@ -1738,10 +2326,10 @@ export {
|
|
|
1738
2326
|
ArticleDetailHero,
|
|
1739
2327
|
ArticleNavigation,
|
|
1740
2328
|
ArticleSEO,
|
|
1741
|
-
ArticleSchema,
|
|
1742
2329
|
ArticleSearchBar,
|
|
1743
2330
|
ArticleSocialShare,
|
|
1744
2331
|
ArticleTOC,
|
|
2332
|
+
ArticleViewTracker,
|
|
1745
2333
|
ArticlesHero,
|
|
1746
2334
|
ArticlesPage,
|
|
1747
2335
|
AuthorArticlesPage,
|
|
@@ -1756,6 +2344,7 @@ export {
|
|
|
1756
2344
|
CommentItem,
|
|
1757
2345
|
CommentThread,
|
|
1758
2346
|
CommentsSection,
|
|
2347
|
+
CtaViewTracker,
|
|
1759
2348
|
DEFAULT_CATEGORIES_PAGE_SIZE,
|
|
1760
2349
|
DEFAULT_LAYOUT,
|
|
1761
2350
|
DEFAULT_PAGE_SIZE,
|
|
@@ -1763,7 +2352,10 @@ export {
|
|
|
1763
2352
|
FeaturedArticle,
|
|
1764
2353
|
LatestArticles,
|
|
1765
2354
|
LatestArticlesSection,
|
|
2355
|
+
PaginationNav,
|
|
2356
|
+
RelatedArticlesSection,
|
|
1766
2357
|
ScrollToTop,
|
|
2358
|
+
SeriesArticlesPage,
|
|
1767
2359
|
breadcrumbsAreEnabled,
|
|
1768
2360
|
getBreadcrumbsConfig,
|
|
1769
2361
|
useArticles
|