@fullstackdatasolutions/articles 0.9.0 → 0.10.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 +237 -0
- package/README.md +199 -29
- package/dist/index.cjs +635 -274
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +160 -56
- package/dist/index.d.ts +160 -56
- package/dist/index.js +614 -250
- package/dist/index.js.map +1 -1
- package/dist/nextjs.cjs +40 -5
- package/dist/nextjs.cjs.map +1 -1
- package/dist/nextjs.d.cts +67 -0
- package/dist/nextjs.d.ts +67 -0
- package/dist/nextjs.js +40 -5
- package/dist/nextjs.js.map +1 -1
- package/dist/server.cjs +278 -15
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +87 -3
- package/dist/server.d.ts +87 -3
- package/dist/server.js +267 -15
- package/dist/server.js.map +1 -1
- package/package.json +8 -5
- package/src/ArticleDetailHero.tsx +27 -2
- package/src/ArticleSchemas.tsx +27 -27
- package/src/AuthorArticlesPage.tsx +60 -0
- package/src/AuthorCard.tsx +112 -0
- package/src/AuthorDetailHero.tsx +56 -0
- package/src/Breadcrumb.tsx +78 -0
- package/src/CategoryArticlesPage.tsx +62 -11
- package/src/__tests__/ArticleDetailHero.test.tsx +21 -1
- package/src/__tests__/ArticleSchemas.test.tsx +47 -2
- package/src/__tests__/AuthorArticlesPage.test.tsx +74 -0
- package/src/__tests__/AuthorCard.test.tsx +98 -0
- package/src/__tests__/AuthorDetailHero.test.tsx +51 -0
- package/src/__tests__/CategoryArticlesPage.test.tsx +31 -5
- package/src/__tests__/authorUtils.test.ts +89 -0
- package/src/__tests__/renderMdx.test.tsx +35 -0
- package/src/__tests__/seoUtils-authors.test.ts +160 -0
- package/src/__tests__/seoUtils.test.ts +4 -0
- package/src/__tests__/server-articles.test.ts +159 -2
- package/src/articleTypes.ts +33 -0
- package/src/articlesConfig.ts +62 -0
- package/src/authorUtils.ts +95 -0
- package/src/index.ts +31 -9
- package/src/renderMdx.tsx +3 -1
- package/src/seoUtils.ts +226 -7
- package/src/server-articles.ts +98 -10
- package/src/server.ts +19 -1
package/dist/server.cjs
CHANGED
|
@@ -81,27 +81,38 @@ var server_exports = {};
|
|
|
81
81
|
__export(server_exports, {
|
|
82
82
|
ArticleContent: () => ArticleContent,
|
|
83
83
|
ArticleTOC: () => ArticleTOC,
|
|
84
|
+
buildArticleBreadcrumbs: () => buildArticleBreadcrumbs,
|
|
85
|
+
buildAuthorBreadcrumbs: () => buildAuthorBreadcrumbs,
|
|
86
|
+
buildCategoryBreadcrumbs: () => buildCategoryBreadcrumbs,
|
|
84
87
|
categoryToSlug: () => categoryToSlug,
|
|
85
88
|
extractToc: () => extractToc,
|
|
86
89
|
generateArticleMetadata: () => generateArticleMetadata,
|
|
87
90
|
generateArticleStaticParams: () => generateArticleStaticParams,
|
|
88
91
|
generateArticlesIndexMetadata: () => generateArticlesIndexMetadata,
|
|
92
|
+
generateAuthorMetadata: () => generateAuthorMetadata,
|
|
93
|
+
generateAuthorStaticParams: () => generateAuthorStaticParams,
|
|
89
94
|
generateCategoryMetadata: () => generateCategoryMetadata,
|
|
90
95
|
generateCategoryStaticParams: () => generateCategoryStaticParams,
|
|
91
96
|
generateRssFeed: () => generateRssFeed,
|
|
92
97
|
getAdjacentArticles: () => getAdjacentArticles,
|
|
93
98
|
getAiRobotsTxtRules: () => getAiRobotsTxtRules,
|
|
94
99
|
getAllArticles: () => getAllArticles,
|
|
100
|
+
getAllAuthors: () => getAllAuthors,
|
|
95
101
|
getAllCategories: () => getAllCategories,
|
|
96
102
|
getArticleAiHeaders: () => getArticleAiHeaders,
|
|
103
|
+
getArticleAuthors: () => getArticleAuthors,
|
|
97
104
|
getArticleMarkdown: () => getArticleMarkdown,
|
|
98
105
|
getArticleMarkdownResponse: () => getArticleMarkdownResponse,
|
|
99
106
|
getArticleMarkdownUrl: () => getArticleMarkdownUrl,
|
|
100
107
|
getArticleMetadata: () => getArticleMetadata,
|
|
101
108
|
getArticleSitemapEntries: () => getArticleSitemapEntries,
|
|
109
|
+
getArticlesByAuthor: () => getArticlesByAuthor,
|
|
102
110
|
getArticlesByCategory: () => getArticlesByCategory,
|
|
111
|
+
getAuthorBySlug: () => getAuthorBySlug,
|
|
103
112
|
getAvailableArticleSlugs: () => getAvailableArticleSlugs,
|
|
113
|
+
getBreadcrumbsConfig: () => getBreadcrumbsConfig,
|
|
104
114
|
markdownToHtml: () => markdownToHtml,
|
|
115
|
+
resolveAuthorAvatar: () => resolveAuthorAvatar,
|
|
105
116
|
sanitizeImagePath: () => sanitizeImagePath2,
|
|
106
117
|
searchArticles: () => searchArticles,
|
|
107
118
|
setArticlesErrorHandler: () => setArticlesErrorHandler
|
|
@@ -578,7 +589,67 @@ function parseHowToSteps(raw) {
|
|
|
578
589
|
);
|
|
579
590
|
return steps.length ? steps : void 0;
|
|
580
591
|
}
|
|
581
|
-
function
|
|
592
|
+
function parseAuthors(raw) {
|
|
593
|
+
if (!Array.isArray(raw)) return void 0;
|
|
594
|
+
const authors = raw.filter(
|
|
595
|
+
(author) => typeof author === "string" && author.trim().length > 0
|
|
596
|
+
);
|
|
597
|
+
return authors;
|
|
598
|
+
}
|
|
599
|
+
function getAuthorBySlug(slug, config) {
|
|
600
|
+
var _a, _b;
|
|
601
|
+
const profile = (_a = config.authors) == null ? void 0 : _a[slug];
|
|
602
|
+
if (!profile) return null;
|
|
603
|
+
return __spreadProps(__spreadValues({}, profile), {
|
|
604
|
+
url: (_b = profile.url) != null ? _b : `${config.siteUrl.replace(/\/$/, "")}/articles/authors/${profile.slug}`
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
function getConfiguredAuthorByName(name, config) {
|
|
608
|
+
var _a;
|
|
609
|
+
const normalizedName = name.trim().toLowerCase();
|
|
610
|
+
const profile = Object.values((_a = config.authors) != null ? _a : {}).find(
|
|
611
|
+
(author) => author.name.toLowerCase() === normalizedName
|
|
612
|
+
);
|
|
613
|
+
return profile ? getAuthorBySlug(profile.slug, config) : null;
|
|
614
|
+
}
|
|
615
|
+
function resolveArticleAuthorName(rawAuthor, rawAuthors, config) {
|
|
616
|
+
var _a, _b, _c, _d;
|
|
617
|
+
const authorArray = parseAuthors(rawAuthors);
|
|
618
|
+
const firstAuthor = authorArray == null ? void 0 : authorArray[0];
|
|
619
|
+
const rawAuthorValue = typeof rawAuthor === "string" && rawAuthor.trim() ? rawAuthor : void 0;
|
|
620
|
+
const author = firstAuthor != null ? firstAuthor : rawAuthorValue;
|
|
621
|
+
const resolved = author != null ? author : config == null ? void 0 : config.defaultAuthor;
|
|
622
|
+
if (!resolved) return "";
|
|
623
|
+
if (!config) return resolved;
|
|
624
|
+
return (_d = (_c = (_a = getAuthorBySlug(resolved, config)) == null ? void 0 : _a.name) != null ? _c : (_b = getConfiguredAuthorByName(resolved, config)) == null ? void 0 : _b.name) != null ? _d : resolved;
|
|
625
|
+
}
|
|
626
|
+
function getArticleAuthors(article, config) {
|
|
627
|
+
var _a;
|
|
628
|
+
const fallbackAuthors = Array.from(
|
|
629
|
+
new Set(
|
|
630
|
+
[article.author, config.defaultAuthor].filter(
|
|
631
|
+
(author) => typeof author === "string" && author.trim().length > 0
|
|
632
|
+
)
|
|
633
|
+
)
|
|
634
|
+
);
|
|
635
|
+
const authorValues = (_a = article.authors) != null ? _a : fallbackAuthors;
|
|
636
|
+
if (authorValues.length === 0) return [];
|
|
637
|
+
const resolvedAuthors = authorValues.map((author) => {
|
|
638
|
+
var _a2;
|
|
639
|
+
return (_a2 = getAuthorBySlug(author, config)) != null ? _a2 : getConfiguredAuthorByName(author, config);
|
|
640
|
+
}).filter((author) => author !== null).filter((author, index, all) => all.findIndex((a) => a.slug === author.slug) === index);
|
|
641
|
+
if (resolvedAuthors.length > 0) return resolvedAuthors;
|
|
642
|
+
return authorValues.map((fallbackName) => ({
|
|
643
|
+
name: fallbackName,
|
|
644
|
+
slug: categoryToSlug(fallbackName),
|
|
645
|
+
bio: ""
|
|
646
|
+
}));
|
|
647
|
+
}
|
|
648
|
+
function getAllAuthors(config) {
|
|
649
|
+
var _a;
|
|
650
|
+
return Object.keys((_a = config.authors) != null ? _a : {}).map((slug) => getAuthorBySlug(slug, config)).filter((author) => author !== null);
|
|
651
|
+
}
|
|
652
|
+
function getArticleSummary(slug, config) {
|
|
582
653
|
return __async(this, null, function* () {
|
|
583
654
|
try {
|
|
584
655
|
const found = findArticleFile(slug);
|
|
@@ -594,7 +665,8 @@ function getArticleSummary(slug) {
|
|
|
594
665
|
excerpt: data.excerpt || "",
|
|
595
666
|
date: parseDateField(data.date),
|
|
596
667
|
lastmod: parseDateField(data.lastmod),
|
|
597
|
-
author: data.author
|
|
668
|
+
author: resolveArticleAuthorName(data.author, data.authors, config),
|
|
669
|
+
authors: parseAuthors(data.authors),
|
|
598
670
|
category: categories[0],
|
|
599
671
|
categories,
|
|
600
672
|
readTime,
|
|
@@ -623,7 +695,7 @@ function getArticleSummary(slug) {
|
|
|
623
695
|
var getArticleMetadata = (0, import_react.cache)(
|
|
624
696
|
(slug, config) => __async(void 0, null, function* () {
|
|
625
697
|
try {
|
|
626
|
-
const summary = yield getArticleSummary(slug);
|
|
698
|
+
const summary = yield getArticleSummary(slug, config);
|
|
627
699
|
if (!summary) return null;
|
|
628
700
|
const found = findArticleFile(slug);
|
|
629
701
|
if (!found) return null;
|
|
@@ -649,9 +721,9 @@ var getArticleMetadata = (0, import_react.cache)(
|
|
|
649
721
|
}
|
|
650
722
|
})
|
|
651
723
|
);
|
|
652
|
-
var getAllArticles = (0, import_react.cache)(() => __async(void 0, null, function* () {
|
|
724
|
+
var getAllArticles = (0, import_react.cache)((config) => __async(void 0, null, function* () {
|
|
653
725
|
const slugs = getAvailableArticleSlugs();
|
|
654
|
-
const articles = yield Promise.all(slugs.map((slug) => getArticleSummary(slug)));
|
|
726
|
+
const articles = yield Promise.all(slugs.map((slug) => getArticleSummary(slug, config)));
|
|
655
727
|
const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
656
728
|
return articles.filter((article) => article !== null).filter((article) => !article.date || article.date <= currentDate).filter((article) => !(article.draft && process.env.NODE_ENV === "production")).sort((a, b) => {
|
|
657
729
|
if (!a.date && !b.date) return 0;
|
|
@@ -741,8 +813,8 @@ function getAiRobotsTxtRules() {
|
|
|
741
813
|
}
|
|
742
814
|
function searchArticles(query, config) {
|
|
743
815
|
return __async(this, null, function* () {
|
|
744
|
-
if (!(query == null ? void 0 : query.trim())) return getAllArticles();
|
|
745
|
-
const articles = yield getAllArticles();
|
|
816
|
+
if (!(query == null ? void 0 : query.trim())) return getAllArticles(config);
|
|
817
|
+
const articles = yield getAllArticles(config);
|
|
746
818
|
const searchTerm = query.toLowerCase().trim();
|
|
747
819
|
const includeAuthor = (config == null ? void 0 : config.showAuthor) !== false;
|
|
748
820
|
return articles.filter((article) => {
|
|
@@ -779,14 +851,33 @@ function getAllCategories() {
|
|
|
779
851
|
})).sort((a, b) => b.count - a.count);
|
|
780
852
|
});
|
|
781
853
|
}
|
|
782
|
-
function getArticlesByCategory(categorySlug) {
|
|
854
|
+
function getArticlesByCategory(categorySlug, config) {
|
|
783
855
|
return __async(this, null, function* () {
|
|
784
|
-
const articles = yield getAllArticles();
|
|
856
|
+
const articles = yield getAllArticles(config);
|
|
785
857
|
return articles.filter(
|
|
786
858
|
(article) => article.categories.some((cat) => categoryToSlug(cat) === categorySlug)
|
|
787
859
|
);
|
|
788
860
|
});
|
|
789
861
|
}
|
|
862
|
+
function getArticlesByAuthor(authorSlug, config) {
|
|
863
|
+
return __async(this, null, function* () {
|
|
864
|
+
const articles = yield getAllArticles(config);
|
|
865
|
+
return articles.filter(
|
|
866
|
+
(article) => getArticleAuthors(article, config).some((author) => author.slug === authorSlug)
|
|
867
|
+
);
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// src/articlesConfig.ts
|
|
872
|
+
function breadcrumbsAreEnabled(config) {
|
|
873
|
+
var _a;
|
|
874
|
+
return config.breadcrumbs !== false && ((_a = config.breadcrumbs) == null ? void 0 : _a.show) !== false;
|
|
875
|
+
}
|
|
876
|
+
function getBreadcrumbsConfig(config) {
|
|
877
|
+
var _a;
|
|
878
|
+
if (config.breadcrumbs === false) return {};
|
|
879
|
+
return (_a = config.breadcrumbs) != null ? _a : {};
|
|
880
|
+
}
|
|
790
881
|
|
|
791
882
|
// src/seoUtils.ts
|
|
792
883
|
function escapeXml(str) {
|
|
@@ -835,6 +926,10 @@ function generateCategoryStaticParams() {
|
|
|
835
926
|
return categories.map((cat) => ({ category: cat.slug }));
|
|
836
927
|
});
|
|
837
928
|
}
|
|
929
|
+
function generateAuthorStaticParams(config) {
|
|
930
|
+
if (config.showAuthorPage === false) return [];
|
|
931
|
+
return getAllAuthors(config).map((author) => ({ author: author.slug }));
|
|
932
|
+
}
|
|
838
933
|
function resolveImageUrl(featuredImage, siteUrl) {
|
|
839
934
|
const base = siteUrl.replace(/\/$/, "");
|
|
840
935
|
if (featuredImage.startsWith("http://") || featuredImage.startsWith("https://")) {
|
|
@@ -845,7 +940,7 @@ function resolveImageUrl(featuredImage, siteUrl) {
|
|
|
845
940
|
function generateArticleMetadata(slug, config) {
|
|
846
941
|
return __async(this, null, function* () {
|
|
847
942
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
848
|
-
const article = yield getArticleMetadata(slug);
|
|
943
|
+
const article = yield getArticleMetadata(slug, config);
|
|
849
944
|
if (!article) {
|
|
850
945
|
return {
|
|
851
946
|
title: "Article Not Found",
|
|
@@ -859,6 +954,7 @@ function generateArticleMetadata(slug, config) {
|
|
|
859
954
|
const description = (_b = article.excerpt) != null ? _b : `Read ${article.title} on ${config.siteName}.`;
|
|
860
955
|
const showAuthor = config.showAuthor !== false;
|
|
861
956
|
const markdownUrl = getArticleMarkdownUrl(article, config);
|
|
957
|
+
const authorNames = getArticleAuthors(article, config).map((author) => author.name);
|
|
862
958
|
return {
|
|
863
959
|
title: `${article.title} | ${config.siteName}`,
|
|
864
960
|
description,
|
|
@@ -871,7 +967,7 @@ function generateArticleMetadata(slug, config) {
|
|
|
871
967
|
images: [{ url: imageUrl, width: 1200, height: 630, alt: article.title }],
|
|
872
968
|
locale: "en_US",
|
|
873
969
|
type: "article"
|
|
874
|
-
}, article.date && { publishedTime: article.date }), article.lastmod && { modifiedTime: new Date(article.lastmod).toISOString() }), showAuthor && { authors:
|
|
970
|
+
}, article.date && { publishedTime: article.date }), article.lastmod && { modifiedTime: new Date(article.lastmod).toISOString() }), showAuthor && authorNames.length > 0 && { authors: authorNames }), {
|
|
875
971
|
tags: (_d = article.tags) != null ? _d : []
|
|
876
972
|
}),
|
|
877
973
|
twitter: {
|
|
@@ -898,7 +994,7 @@ function generateArticleMetadata(slug, config) {
|
|
|
898
994
|
"max-snippet": -1
|
|
899
995
|
}
|
|
900
996
|
},
|
|
901
|
-
other: __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, showAuthor && { "article:author":
|
|
997
|
+
other: __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, showAuthor && authorNames.length > 0 && { "article:author": authorNames.join(", ") }), article.date && {
|
|
902
998
|
"article:published_time": new Date(article.date).toISOString()
|
|
903
999
|
}), article.lastmod && {
|
|
904
1000
|
"article:modified_time": new Date(article.lastmod).toISOString()
|
|
@@ -997,11 +1093,162 @@ function generateCategoryMetadata(categorySlug, config) {
|
|
|
997
1093
|
};
|
|
998
1094
|
});
|
|
999
1095
|
}
|
|
1096
|
+
function generateAuthorMetadata(authorSlug, config) {
|
|
1097
|
+
return __async(this, null, function* () {
|
|
1098
|
+
var _a;
|
|
1099
|
+
const author = getAuthorBySlug(authorSlug, config);
|
|
1100
|
+
if (!author || config.showAuthorPage === false) return { title: "Author Not Found" };
|
|
1101
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1102
|
+
const authorUrl = (_a = author.url) != null ? _a : `${siteUrl}/articles/authors/${author.slug}`;
|
|
1103
|
+
const title = `${author.name} Articles | ${config.siteName}`;
|
|
1104
|
+
return {
|
|
1105
|
+
title,
|
|
1106
|
+
description: author.bio,
|
|
1107
|
+
openGraph: __spreadValues({
|
|
1108
|
+
title,
|
|
1109
|
+
description: author.bio,
|
|
1110
|
+
url: authorUrl,
|
|
1111
|
+
siteName: config.siteName,
|
|
1112
|
+
type: "profile",
|
|
1113
|
+
locale: "en_US"
|
|
1114
|
+
}, author.avatar && { images: [{ url: resolveAuthorAvatar(author, config) }] }),
|
|
1115
|
+
twitter: __spreadValues({
|
|
1116
|
+
card: "summary_large_image",
|
|
1117
|
+
title,
|
|
1118
|
+
description: author.bio
|
|
1119
|
+
}, author.avatar && { images: [resolveAuthorAvatar(author, config)] }),
|
|
1120
|
+
alternates: {
|
|
1121
|
+
canonical: authorUrl
|
|
1122
|
+
},
|
|
1123
|
+
robots: {
|
|
1124
|
+
index: true,
|
|
1125
|
+
follow: true
|
|
1126
|
+
}
|
|
1127
|
+
};
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
function formatCategoryName(category) {
|
|
1131
|
+
return category.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
1132
|
+
}
|
|
1133
|
+
function buildArticleBreadcrumbs(article, config) {
|
|
1134
|
+
var _a, _b;
|
|
1135
|
+
if (!breadcrumbsAreEnabled(config)) return [];
|
|
1136
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1137
|
+
const breadcrumbConfig = getBreadcrumbsConfig(config);
|
|
1138
|
+
const labels = (_a = breadcrumbConfig.labels) != null ? _a : {};
|
|
1139
|
+
const categorySlug = categoryToSlug(article.category);
|
|
1140
|
+
const trail = (_b = breadcrumbConfig.article) != null ? _b : ["home", "articles", "primaryCategory", "articleTitle"];
|
|
1141
|
+
const folderSegments = article.slug.split("/").filter(Boolean).slice(0, -1);
|
|
1142
|
+
return trail.flatMap(
|
|
1143
|
+
(token) => buildArticleBreadcrumbToken(token, {
|
|
1144
|
+
article,
|
|
1145
|
+
siteUrl,
|
|
1146
|
+
categorySlug,
|
|
1147
|
+
folderSegments,
|
|
1148
|
+
labels
|
|
1149
|
+
})
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
function buildCategoryBreadcrumbs(category, config, categoryName = formatCategoryName(category)) {
|
|
1153
|
+
var _a, _b;
|
|
1154
|
+
if (!breadcrumbsAreEnabled(config)) return [];
|
|
1155
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1156
|
+
const breadcrumbConfig = getBreadcrumbsConfig(config);
|
|
1157
|
+
const labels = (_a = breadcrumbConfig.labels) != null ? _a : {};
|
|
1158
|
+
const trail = (_b = breadcrumbConfig.category) != null ? _b : ["home", "articles", "category"];
|
|
1159
|
+
return trail.flatMap(
|
|
1160
|
+
(entry) => buildCategoryBreadcrumbEntry(entry, { categoryName, siteUrl, labels })
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
function buildAuthorBreadcrumbs(author, config) {
|
|
1164
|
+
var _a, _b;
|
|
1165
|
+
if (!breadcrumbsAreEnabled(config)) return [];
|
|
1166
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1167
|
+
const breadcrumbConfig = getBreadcrumbsConfig(config);
|
|
1168
|
+
const labels = (_a = breadcrumbConfig.labels) != null ? _a : {};
|
|
1169
|
+
const trail = (_b = breadcrumbConfig.author) != null ? _b : ["home", "articles", "authors", "authorName"];
|
|
1170
|
+
return trail.flatMap(
|
|
1171
|
+
(entry) => buildAuthorBreadcrumbEntry(entry, { author, siteUrl, labels })
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
function isCustomBreadcrumbItem(entry) {
|
|
1175
|
+
return typeof entry === "object" && entry !== null && "name" in entry && "url" in entry;
|
|
1176
|
+
}
|
|
1177
|
+
function resolveCustomBreadcrumbItem(item, siteUrl) {
|
|
1178
|
+
if (item.url.startsWith("/")) return { name: item.name, url: `${siteUrl}${item.url}` };
|
|
1179
|
+
return { name: item.name, url: item.url };
|
|
1180
|
+
}
|
|
1181
|
+
function buildArticleBreadcrumbToken(entry, context) {
|
|
1182
|
+
var _a, _b;
|
|
1183
|
+
if (isCustomBreadcrumbItem(entry)) {
|
|
1184
|
+
return [resolveCustomBreadcrumbItem(entry, context.siteUrl)];
|
|
1185
|
+
}
|
|
1186
|
+
if (entry === "home") return [{ name: (_a = context.labels.home) != null ? _a : "Home", url: context.siteUrl }];
|
|
1187
|
+
if (entry === "articles") {
|
|
1188
|
+
return [{ name: (_b = context.labels.articles) != null ? _b : "Articles", url: `${context.siteUrl}/articles` }];
|
|
1189
|
+
}
|
|
1190
|
+
if (entry === "primaryCategory") {
|
|
1191
|
+
return [
|
|
1192
|
+
{
|
|
1193
|
+
name: context.article.category,
|
|
1194
|
+
url: `${context.siteUrl}/articles/category/${context.categorySlug}`
|
|
1195
|
+
}
|
|
1196
|
+
];
|
|
1197
|
+
}
|
|
1198
|
+
if (entry === "folderPath") {
|
|
1199
|
+
return context.folderSegments.map((segment, index) => ({
|
|
1200
|
+
name: formatCategoryName(segment),
|
|
1201
|
+
url: `${context.siteUrl}/articles/${context.folderSegments.slice(0, index + 1).join("/")}`
|
|
1202
|
+
}));
|
|
1203
|
+
}
|
|
1204
|
+
return [{ name: context.article.title }];
|
|
1205
|
+
}
|
|
1206
|
+
function buildCategoryBreadcrumbEntry(entry, context) {
|
|
1207
|
+
var _a, _b;
|
|
1208
|
+
if (isCustomBreadcrumbItem(entry)) {
|
|
1209
|
+
return [resolveCustomBreadcrumbItem(entry, context.siteUrl)];
|
|
1210
|
+
}
|
|
1211
|
+
if (entry === "home") return [{ name: (_a = context.labels.home) != null ? _a : "Home", url: context.siteUrl }];
|
|
1212
|
+
if (entry === "articles") {
|
|
1213
|
+
return [{ name: (_b = context.labels.articles) != null ? _b : "Articles", url: `${context.siteUrl}/articles` }];
|
|
1214
|
+
}
|
|
1215
|
+
return [{ name: context.categoryName }];
|
|
1216
|
+
}
|
|
1217
|
+
function buildAuthorBreadcrumbEntry(entry, context) {
|
|
1218
|
+
var _a, _b, _c;
|
|
1219
|
+
if (isCustomBreadcrumbItem(entry)) {
|
|
1220
|
+
return [resolveCustomBreadcrumbItem(entry, context.siteUrl)];
|
|
1221
|
+
}
|
|
1222
|
+
if (entry === "home") return [{ name: (_a = context.labels.home) != null ? _a : "Home", url: context.siteUrl }];
|
|
1223
|
+
if (entry === "articles") {
|
|
1224
|
+
return [{ name: (_b = context.labels.articles) != null ? _b : "Articles", url: `${context.siteUrl}/articles` }];
|
|
1225
|
+
}
|
|
1226
|
+
if (entry === "authors") {
|
|
1227
|
+
return [
|
|
1228
|
+
{
|
|
1229
|
+
name: (_c = context.labels.authors) != null ? _c : "Authors",
|
|
1230
|
+
url: `${context.siteUrl}/articles/authors`
|
|
1231
|
+
}
|
|
1232
|
+
];
|
|
1233
|
+
}
|
|
1234
|
+
return [{ name: context.author.name }];
|
|
1235
|
+
}
|
|
1236
|
+
function resolveAuthorAvatar(author, config) {
|
|
1237
|
+
if (!author.avatar) return "";
|
|
1238
|
+
if (author.avatar.startsWith("http://") || author.avatar.startsWith("https://")) {
|
|
1239
|
+
return author.avatar;
|
|
1240
|
+
}
|
|
1241
|
+
const siteUrl = config.siteUrl.replace(/\/$/, "");
|
|
1242
|
+
return `${siteUrl}/articles/authors/${author.slug}/${author.avatar.replace(/^\/+/, "")}`;
|
|
1243
|
+
}
|
|
1000
1244
|
function getArticleSitemapEntries(baseUrlOrConfig) {
|
|
1001
1245
|
return __async(this, null, function* () {
|
|
1002
1246
|
const baseUrl = (typeof baseUrlOrConfig === "string" ? baseUrlOrConfig : baseUrlOrConfig.siteUrl).replace(/\/$/, "");
|
|
1003
1247
|
try {
|
|
1004
|
-
const [articles, categories] = yield Promise.all([
|
|
1248
|
+
const [articles, categories] = yield Promise.all([
|
|
1249
|
+
getAllArticles(typeof baseUrlOrConfig === "string" ? void 0 : baseUrlOrConfig),
|
|
1250
|
+
getAllCategories()
|
|
1251
|
+
]);
|
|
1005
1252
|
const articleEntries = articles.map((article) => {
|
|
1006
1253
|
var _a;
|
|
1007
1254
|
const dateStr = (_a = article.lastmod) != null ? _a : article.date;
|
|
@@ -1019,7 +1266,12 @@ function getArticleSitemapEntries(baseUrlOrConfig) {
|
|
|
1019
1266
|
changeFrequency: "weekly",
|
|
1020
1267
|
priority: 0.7
|
|
1021
1268
|
}));
|
|
1022
|
-
|
|
1269
|
+
const authorEntries = typeof baseUrlOrConfig === "string" || baseUrlOrConfig.showAuthorPage === false ? [] : getAllAuthors(baseUrlOrConfig).map((author) => ({
|
|
1270
|
+
url: `${baseUrl}/articles/authors/${author.slug}`,
|
|
1271
|
+
changeFrequency: "monthly",
|
|
1272
|
+
priority: 0.6
|
|
1273
|
+
}));
|
|
1274
|
+
return [...articleEntries, ...categoryEntries, ...authorEntries];
|
|
1023
1275
|
} catch (e) {
|
|
1024
1276
|
return [];
|
|
1025
1277
|
}
|
|
@@ -1039,7 +1291,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
1039
1291
|
function makeImgComponent(basePath) {
|
|
1040
1292
|
return function MdxImage(_a) {
|
|
1041
1293
|
var _b = _a, { src, alt } = _b, props = __objRest(_b, ["src", "alt"]);
|
|
1042
|
-
const resolvedSrc = src && !src.startsWith("http") && !src.startsWith("/") ? `${basePath}/${src}` : src;
|
|
1294
|
+
const resolvedSrc = typeof src === "string" && !src.startsWith("http") && !src.startsWith("/") ? `${basePath}/${src}` : src;
|
|
1043
1295
|
return import_react2.default.createElement("img", __spreadValues({ src: resolvedSrc, alt }, props));
|
|
1044
1296
|
};
|
|
1045
1297
|
}
|
|
@@ -1101,27 +1353,38 @@ function ArticleTOC({ toc, className }) {
|
|
|
1101
1353
|
0 && (module.exports = {
|
|
1102
1354
|
ArticleContent,
|
|
1103
1355
|
ArticleTOC,
|
|
1356
|
+
buildArticleBreadcrumbs,
|
|
1357
|
+
buildAuthorBreadcrumbs,
|
|
1358
|
+
buildCategoryBreadcrumbs,
|
|
1104
1359
|
categoryToSlug,
|
|
1105
1360
|
extractToc,
|
|
1106
1361
|
generateArticleMetadata,
|
|
1107
1362
|
generateArticleStaticParams,
|
|
1108
1363
|
generateArticlesIndexMetadata,
|
|
1364
|
+
generateAuthorMetadata,
|
|
1365
|
+
generateAuthorStaticParams,
|
|
1109
1366
|
generateCategoryMetadata,
|
|
1110
1367
|
generateCategoryStaticParams,
|
|
1111
1368
|
generateRssFeed,
|
|
1112
1369
|
getAdjacentArticles,
|
|
1113
1370
|
getAiRobotsTxtRules,
|
|
1114
1371
|
getAllArticles,
|
|
1372
|
+
getAllAuthors,
|
|
1115
1373
|
getAllCategories,
|
|
1116
1374
|
getArticleAiHeaders,
|
|
1375
|
+
getArticleAuthors,
|
|
1117
1376
|
getArticleMarkdown,
|
|
1118
1377
|
getArticleMarkdownResponse,
|
|
1119
1378
|
getArticleMarkdownUrl,
|
|
1120
1379
|
getArticleMetadata,
|
|
1121
1380
|
getArticleSitemapEntries,
|
|
1381
|
+
getArticlesByAuthor,
|
|
1122
1382
|
getArticlesByCategory,
|
|
1383
|
+
getAuthorBySlug,
|
|
1123
1384
|
getAvailableArticleSlugs,
|
|
1385
|
+
getBreadcrumbsConfig,
|
|
1124
1386
|
markdownToHtml,
|
|
1387
|
+
resolveAuthorAvatar,
|
|
1125
1388
|
sanitizeImagePath,
|
|
1126
1389
|
searchArticles,
|
|
1127
1390
|
setArticlesErrorHandler
|