@founderhq/next-blog 0.9.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/README.md +169 -0
- package/dist/cli/core.d.ts +61 -0
- package/dist/cli/core.d.ts.map +1 -0
- package/dist/cli/core.js +1983 -0
- package/dist/cli/core.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +390 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/components.d.ts +57 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +281 -0
- package/dist/components.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/registry.d.ts +6 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +29 -0
- package/dist/registry.js.map +1 -0
- package/dist/server.d.ts +159 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +681 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +21 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +56 -0
- package/dist/utils.js.map +1 -0
- package/package.json +88 -0
- package/src/styles.css +264 -0
- package/src/templates/blog-components.tsx.txt +603 -0
- package/src/templates/blog.css.txt +264 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
import { absoluteUrl, articlePath, articleUrl, authorPath, blogIndexPath, categoryPath, dateToIso, escapeHtml, imageUrl, normalizeRoutePrefix, stripHtml, tagPath, } from "./utils.js";
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function readString(value) {
|
|
6
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
7
|
+
}
|
|
8
|
+
function readNumber(value) {
|
|
9
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
10
|
+
}
|
|
11
|
+
function hasNoIndex(article) {
|
|
12
|
+
var _a, _b, _c;
|
|
13
|
+
return (_c = (_b = (_a = article.seo) === null || _a === void 0 ? void 0 : _a.robots) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes("noindex")) !== null && _c !== void 0 ? _c : false;
|
|
14
|
+
}
|
|
15
|
+
function articleCanonicalUrl(article, site) {
|
|
16
|
+
var _a, _b;
|
|
17
|
+
return absoluteUrl(site.siteUrl, ((_b = (_a = article.seo) === null || _a === void 0 ? void 0 : _a.canonicalUrl) === null || _b === void 0 ? void 0 : _b.trim()) || articlePath(article, site));
|
|
18
|
+
}
|
|
19
|
+
function hasSameSiteCanonical(article, site) {
|
|
20
|
+
var _a, _b;
|
|
21
|
+
if (!((_b = (_a = article.seo) === null || _a === void 0 ? void 0 : _a.canonicalUrl) === null || _b === void 0 ? void 0 : _b.trim()))
|
|
22
|
+
return true;
|
|
23
|
+
try {
|
|
24
|
+
return (new URL(articleCanonicalUrl(article, site)).origin ===
|
|
25
|
+
new URL(site.siteUrl).origin);
|
|
26
|
+
}
|
|
27
|
+
catch (_c) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function isIndexableBlogArticle(article, site) {
|
|
32
|
+
return !hasNoIndex(article) && hasSameSiteCanonical(article, site);
|
|
33
|
+
}
|
|
34
|
+
function stripTags(value) {
|
|
35
|
+
return value
|
|
36
|
+
.replace(/<script[\s\S]*?<\/script>/gi, "")
|
|
37
|
+
.replace(/<style[\s\S]*?<\/style>/gi, "")
|
|
38
|
+
.replace(/<[^>]*>/g, " ")
|
|
39
|
+
.replace(/\s+/g, " ")
|
|
40
|
+
.trim();
|
|
41
|
+
}
|
|
42
|
+
function headingSlug(text, fallback) {
|
|
43
|
+
const slug = text
|
|
44
|
+
.toLowerCase()
|
|
45
|
+
.trim()
|
|
46
|
+
.replace(/[^\w\s-]/g, "")
|
|
47
|
+
.replace(/[\s_]+/g, "-")
|
|
48
|
+
.replace(/^-+|-+$/g, "");
|
|
49
|
+
return slug || `heading-${fallback}`;
|
|
50
|
+
}
|
|
51
|
+
function uniqueHeadingId(text, index, used) {
|
|
52
|
+
var _a;
|
|
53
|
+
const base = headingSlug(text, index);
|
|
54
|
+
const seen = (_a = used.get(base)) !== null && _a !== void 0 ? _a : 0;
|
|
55
|
+
used.set(base, seen + 1);
|
|
56
|
+
return seen === 0 ? base : `${base}-${seen + 1}`;
|
|
57
|
+
}
|
|
58
|
+
export function addHeadingIdsAndExtractToc(html) {
|
|
59
|
+
const toc = [];
|
|
60
|
+
const used = new Map();
|
|
61
|
+
const nextHtml = html.replace(/<h([1-6])([^>]*)>([\s\S]*?)<\/h\1>/gi, (match, rawLevel, rawAttrs, inner) => {
|
|
62
|
+
var _a, _b, _c, _d;
|
|
63
|
+
const level = Number(rawLevel);
|
|
64
|
+
const text = stripTags(inner);
|
|
65
|
+
if (!text || level < 2)
|
|
66
|
+
return match;
|
|
67
|
+
const existingId = (_c = (_b = (_a = /\sid=(["'])(.*?)\1/i.exec(rawAttrs)) === null || _a === void 0 ? void 0 : _a[2]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : null;
|
|
68
|
+
const id = existingId || uniqueHeadingId(text, toc.length + 1, used);
|
|
69
|
+
toc.push({ id, text, level });
|
|
70
|
+
if (existingId) {
|
|
71
|
+
used.set(existingId, ((_d = used.get(existingId)) !== null && _d !== void 0 ? _d : 0) + 1);
|
|
72
|
+
return match;
|
|
73
|
+
}
|
|
74
|
+
return `<h${level}${rawAttrs} id="${id}">${inner}</h${level}>`;
|
|
75
|
+
});
|
|
76
|
+
return { html: nextHtml, toc };
|
|
77
|
+
}
|
|
78
|
+
function readImage(value) {
|
|
79
|
+
if (!isRecord(value))
|
|
80
|
+
return null;
|
|
81
|
+
const url = readString(value.url);
|
|
82
|
+
const alt = readString(value.alt);
|
|
83
|
+
if (!url || !alt)
|
|
84
|
+
return null;
|
|
85
|
+
return {
|
|
86
|
+
url,
|
|
87
|
+
alt,
|
|
88
|
+
width: readNumber(value.width),
|
|
89
|
+
height: readNumber(value.height),
|
|
90
|
+
aspectRatio: readString(value.aspectRatio),
|
|
91
|
+
caption: readString(value.caption),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function readAuthor(value) {
|
|
95
|
+
if (!isRecord(value))
|
|
96
|
+
return null;
|
|
97
|
+
const name = readString(value.name);
|
|
98
|
+
if (!name)
|
|
99
|
+
return null;
|
|
100
|
+
return {
|
|
101
|
+
id: typeof value.id === "string" || typeof value.id === "number"
|
|
102
|
+
? value.id
|
|
103
|
+
: undefined,
|
|
104
|
+
name,
|
|
105
|
+
slug: readString(value.slug),
|
|
106
|
+
title: readString(value.title),
|
|
107
|
+
bio: readString(value.bio),
|
|
108
|
+
avatar: readImage(value.avatar),
|
|
109
|
+
profileUrl: readString(value.profileUrl),
|
|
110
|
+
sameAs: Array.isArray(value.sameAs)
|
|
111
|
+
? value.sameAs
|
|
112
|
+
.map((item) => (isRecord(item) ? readString(item.url) : readString(item)))
|
|
113
|
+
.filter((item) => Boolean(item))
|
|
114
|
+
: undefined,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function normalizePayloadBlogAuthor(doc) {
|
|
118
|
+
var _a;
|
|
119
|
+
return {
|
|
120
|
+
id: typeof doc.id === "string" || typeof doc.id === "number"
|
|
121
|
+
? doc.id
|
|
122
|
+
: undefined,
|
|
123
|
+
name: (_a = readString(doc.name)) !== null && _a !== void 0 ? _a : "Unknown author",
|
|
124
|
+
slug: readString(doc.slug),
|
|
125
|
+
title: readString(doc.title),
|
|
126
|
+
bio: readString(doc.bio),
|
|
127
|
+
avatar: readImage(doc.avatar),
|
|
128
|
+
profileUrl: readString(doc.profileUrl),
|
|
129
|
+
sameAs: Array.isArray(doc.sameAs)
|
|
130
|
+
? doc.sameAs
|
|
131
|
+
.map((item) => (isRecord(item) ? readString(item.url) : readString(item)))
|
|
132
|
+
.filter((item) => Boolean(item))
|
|
133
|
+
: undefined,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function readTaxonomies(value) {
|
|
137
|
+
const items = Array.isArray(value) ? value : value ? [value] : [];
|
|
138
|
+
return items.flatMap((item) => {
|
|
139
|
+
if (!isRecord(item))
|
|
140
|
+
return [];
|
|
141
|
+
const title = readString(item.title);
|
|
142
|
+
const slug = readString(item.slug);
|
|
143
|
+
if (!title || !slug)
|
|
144
|
+
return [];
|
|
145
|
+
return [
|
|
146
|
+
{
|
|
147
|
+
id: typeof item.id === "string" || typeof item.id === "number"
|
|
148
|
+
? item.id
|
|
149
|
+
: undefined,
|
|
150
|
+
title,
|
|
151
|
+
slug,
|
|
152
|
+
description: readString(item.description),
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
export function normalizePayloadBlogTaxonomy(doc) {
|
|
158
|
+
var _a, _b, _c;
|
|
159
|
+
return {
|
|
160
|
+
id: typeof doc.id === "string" || typeof doc.id === "number"
|
|
161
|
+
? doc.id
|
|
162
|
+
: undefined,
|
|
163
|
+
title: (_a = readString(doc.title)) !== null && _a !== void 0 ? _a : "Untitled",
|
|
164
|
+
slug: (_b = readString(doc.slug)) !== null && _b !== void 0 ? _b : String((_c = doc.id) !== null && _c !== void 0 ? _c : ""),
|
|
165
|
+
description: readString(doc.description),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
export function normalizePayloadBlogArticle(doc) {
|
|
169
|
+
var _a, _b, _c, _d;
|
|
170
|
+
const content = addHeadingIdsAndExtractToc((_a = readString(doc.contentHtml)) !== null && _a !== void 0 ? _a : "");
|
|
171
|
+
const seo = isRecord(doc.seo) ? doc.seo : {};
|
|
172
|
+
return {
|
|
173
|
+
id: typeof doc.id === "string" || typeof doc.id === "number"
|
|
174
|
+
? doc.id
|
|
175
|
+
: undefined,
|
|
176
|
+
title: (_b = readString(doc.title)) !== null && _b !== void 0 ? _b : "Untitled",
|
|
177
|
+
slug: (_c = readString(doc.slug)) !== null && _c !== void 0 ? _c : String((_d = doc.id) !== null && _d !== void 0 ? _d : ""),
|
|
178
|
+
excerpt: readString(doc.excerpt),
|
|
179
|
+
contentHtml: content.html,
|
|
180
|
+
searchText: readString(doc.searchText),
|
|
181
|
+
author: readAuthor(doc.author),
|
|
182
|
+
categories: readTaxonomies(doc.categories),
|
|
183
|
+
tags: readTaxonomies(doc.tags),
|
|
184
|
+
featuredImage: readImage(doc.featuredImage),
|
|
185
|
+
publishedAt: readString(doc.publishedAt),
|
|
186
|
+
updatedAt: readString(doc.updatedAt),
|
|
187
|
+
language: readString(doc.language),
|
|
188
|
+
seo: {
|
|
189
|
+
metaTitle: readString(seo.metaTitle),
|
|
190
|
+
metaDescription: readString(seo.metaDescription),
|
|
191
|
+
canonicalUrl: readString(seo.canonicalUrl),
|
|
192
|
+
robots: readString(seo.robots),
|
|
193
|
+
ogImage: readImage(seo.ogImage),
|
|
194
|
+
schemaOverride: isRecord(seo.schemaOverride) ? seo.schemaOverride : null,
|
|
195
|
+
},
|
|
196
|
+
toc: content.toc,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
export function normalizePayloadBlogListResult(result) {
|
|
200
|
+
return Object.assign(Object.assign({}, result), { docs: result.docs.map(normalizePayloadBlogArticle) });
|
|
201
|
+
}
|
|
202
|
+
export function paginateBlogArticles(articles, page = 1, limit = 12) {
|
|
203
|
+
const safeLimit = Math.max(1, Math.floor(limit));
|
|
204
|
+
const totalDocs = articles.length;
|
|
205
|
+
const totalPages = Math.max(1, Math.ceil(totalDocs / safeLimit));
|
|
206
|
+
const safePage = Math.min(Math.max(1, Math.floor(page)), totalPages);
|
|
207
|
+
const start = (safePage - 1) * safeLimit;
|
|
208
|
+
return {
|
|
209
|
+
docs: articles.slice(start, start + safeLimit),
|
|
210
|
+
totalDocs,
|
|
211
|
+
page: safePage,
|
|
212
|
+
totalPages,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
export function buildBlogPagination(params) {
|
|
216
|
+
var _a;
|
|
217
|
+
const basePath = (_a = params.basePath) !== null && _a !== void 0 ? _a : normalizeRoutePrefix(params.site.routePrefix);
|
|
218
|
+
const pagePath = (page) => page <= 1 ? basePath || "/" : `${basePath.replace(/\/$/, "")}/page/${page}`;
|
|
219
|
+
return {
|
|
220
|
+
page: params.page,
|
|
221
|
+
totalPages: params.totalPages,
|
|
222
|
+
totalDocs: params.totalDocs,
|
|
223
|
+
prevHref: params.page > 1 ? pagePath(params.page - 1) : null,
|
|
224
|
+
nextHref: params.page < params.totalPages ? pagePath(params.page + 1) : null,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
export function buildArticleMetadata(article, site) {
|
|
228
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
229
|
+
const canonical = articleCanonicalUrl(article, site);
|
|
230
|
+
const description = ((_b = (_a = article.seo) === null || _a === void 0 ? void 0 : _a.metaDescription) === null || _b === void 0 ? void 0 : _b.trim()) ||
|
|
231
|
+
((_c = article.excerpt) === null || _c === void 0 ? void 0 : _c.trim()) ||
|
|
232
|
+
stripHtml((_d = article.contentHtml) !== null && _d !== void 0 ? _d : "").slice(0, 220);
|
|
233
|
+
const title = ((_f = (_e = article.seo) === null || _e === void 0 ? void 0 : _e.metaTitle) === null || _f === void 0 ? void 0 : _f.trim()) || article.title;
|
|
234
|
+
const image = (_j = (_h = (_g = article.seo) === null || _g === void 0 ? void 0 : _g.ogImage) !== null && _h !== void 0 ? _h : article.featuredImage) !== null && _j !== void 0 ? _j : site.defaultOgImage;
|
|
235
|
+
const imageAbsolute = imageUrl(image, site);
|
|
236
|
+
const index = !hasNoIndex(article);
|
|
237
|
+
return {
|
|
238
|
+
title,
|
|
239
|
+
description,
|
|
240
|
+
canonical,
|
|
241
|
+
robots: {
|
|
242
|
+
index,
|
|
243
|
+
follow: true,
|
|
244
|
+
googleBot: {
|
|
245
|
+
index,
|
|
246
|
+
follow: true,
|
|
247
|
+
"max-image-preview": "large",
|
|
248
|
+
"max-snippet": -1,
|
|
249
|
+
"max-video-preview": -1,
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
openGraph: Object.assign(Object.assign(Object.assign(Object.assign({ type: "article", url: canonical, siteName: site.siteName, title,
|
|
253
|
+
description }, (dateToIso(article.publishedAt)
|
|
254
|
+
? { publishedTime: (_k = dateToIso(article.publishedAt)) !== null && _k !== void 0 ? _k : undefined }
|
|
255
|
+
: {})), (dateToIso(article.updatedAt)
|
|
256
|
+
? { modifiedTime: (_l = dateToIso(article.updatedAt)) !== null && _l !== void 0 ? _l : undefined }
|
|
257
|
+
: {})), (((_m = article.author) === null || _m === void 0 ? void 0 : _m.name) ? { authors: [article.author.name] } : {})), (imageAbsolute
|
|
258
|
+
? {
|
|
259
|
+
images: [
|
|
260
|
+
Object.assign(Object.assign(Object.assign({ url: imageAbsolute }, ((image === null || image === void 0 ? void 0 : image.width) ? { width: image.width } : {})), ((image === null || image === void 0 ? void 0 : image.height) ? { height: image.height } : {})), { alt: (_o = image === null || image === void 0 ? void 0 : image.alt) !== null && _o !== void 0 ? _o : title }),
|
|
261
|
+
],
|
|
262
|
+
}
|
|
263
|
+
: {})),
|
|
264
|
+
twitter: Object.assign({ card: "summary_large_image", title,
|
|
265
|
+
description }, (imageAbsolute ? { images: [imageAbsolute] } : {})),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
export function buildArticleJsonLd(article, site) {
|
|
269
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
|
|
270
|
+
const url = articleCanonicalUrl(article, site);
|
|
271
|
+
const image = (_a = article.featuredImage) !== null && _a !== void 0 ? _a : site.defaultOgImage;
|
|
272
|
+
const imageAbsolute = imageUrl(image, site);
|
|
273
|
+
const siteRoot = site.siteUrl.replace(/\/$/, "");
|
|
274
|
+
const organizationId = `${siteRoot}/#organization`;
|
|
275
|
+
const websiteId = `${siteRoot}/#website`;
|
|
276
|
+
const webpageId = `${url}#webpage`;
|
|
277
|
+
const articleId = `${url}#article`;
|
|
278
|
+
const imageId = imageAbsolute ? `${url}#primaryimage` : null;
|
|
279
|
+
const authorId = article.author
|
|
280
|
+
? (_b = article.author.profileUrl) !== null && _b !== void 0 ? _b : `${url}#author`
|
|
281
|
+
: organizationId;
|
|
282
|
+
const graph = [
|
|
283
|
+
{
|
|
284
|
+
"@type": "WebSite",
|
|
285
|
+
"@id": websiteId,
|
|
286
|
+
name: site.siteName,
|
|
287
|
+
url: site.siteUrl,
|
|
288
|
+
publisher: {
|
|
289
|
+
"@id": organizationId,
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
Object.assign({ "@type": "Organization", "@id": organizationId, name: (_c = site.organizationName) !== null && _c !== void 0 ? _c : site.siteName, url: site.siteUrl }, (site.organizationLogoUrl
|
|
293
|
+
? { logo: { "@type": "ImageObject", url: site.organizationLogoUrl } }
|
|
294
|
+
: {})),
|
|
295
|
+
{
|
|
296
|
+
"@type": "WebPage",
|
|
297
|
+
"@id": webpageId,
|
|
298
|
+
url,
|
|
299
|
+
name: (_e = (_d = article.seo) === null || _d === void 0 ? void 0 : _d.metaTitle) !== null && _e !== void 0 ? _e : article.title,
|
|
300
|
+
isPartOf: { "@id": websiteId },
|
|
301
|
+
primaryImageOfPage: imageId ? { "@id": imageId } : undefined,
|
|
302
|
+
breadcrumb: { "@id": `${url}#breadcrumb` },
|
|
303
|
+
inLanguage: (_g = (_f = article.language) !== null && _f !== void 0 ? _f : site.defaultLanguage) !== null && _g !== void 0 ? _g : "en",
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"@type": "BreadcrumbList",
|
|
307
|
+
"@id": `${url}#breadcrumb`,
|
|
308
|
+
itemListElement: [
|
|
309
|
+
{
|
|
310
|
+
"@type": "ListItem",
|
|
311
|
+
position: 1,
|
|
312
|
+
name: "Blog",
|
|
313
|
+
item: absoluteUrl(site.siteUrl, normalizeRoutePrefix(site.routePrefix)),
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"@type": "ListItem",
|
|
317
|
+
position: 2,
|
|
318
|
+
name: article.title,
|
|
319
|
+
item: url,
|
|
320
|
+
},
|
|
321
|
+
],
|
|
322
|
+
},
|
|
323
|
+
...(article.author
|
|
324
|
+
? [
|
|
325
|
+
{
|
|
326
|
+
"@type": "Person",
|
|
327
|
+
"@id": authorId,
|
|
328
|
+
name: article.author.name,
|
|
329
|
+
url: (_h = article.author.profileUrl) !== null && _h !== void 0 ? _h : undefined,
|
|
330
|
+
sameAs: ((_j = article.author.sameAs) === null || _j === void 0 ? void 0 : _j.length)
|
|
331
|
+
? article.author.sameAs
|
|
332
|
+
: undefined,
|
|
333
|
+
},
|
|
334
|
+
]
|
|
335
|
+
: []),
|
|
336
|
+
...(imageAbsolute
|
|
337
|
+
? [
|
|
338
|
+
{
|
|
339
|
+
"@type": "ImageObject",
|
|
340
|
+
"@id": imageId,
|
|
341
|
+
url: imageAbsolute,
|
|
342
|
+
width: (_k = image === null || image === void 0 ? void 0 : image.width) !== null && _k !== void 0 ? _k : undefined,
|
|
343
|
+
height: (_l = image === null || image === void 0 ? void 0 : image.height) !== null && _l !== void 0 ? _l : undefined,
|
|
344
|
+
caption: (_m = image === null || image === void 0 ? void 0 : image.caption) !== null && _m !== void 0 ? _m : undefined,
|
|
345
|
+
},
|
|
346
|
+
]
|
|
347
|
+
: []),
|
|
348
|
+
Object.assign(Object.assign({ "@type": "BlogPosting", "@id": articleId, headline: article.title, description: (_q = (_o = article.excerpt) !== null && _o !== void 0 ? _o : (_p = article.seo) === null || _p === void 0 ? void 0 : _p.metaDescription) !== null && _q !== void 0 ? _q : undefined, url, mainEntityOfPage: {
|
|
349
|
+
"@id": webpageId,
|
|
350
|
+
}, inLanguage: (_s = (_r = article.language) !== null && _r !== void 0 ? _r : site.defaultLanguage) !== null && _s !== void 0 ? _s : "en", datePublished: (_t = dateToIso(article.publishedAt)) !== null && _t !== void 0 ? _t : undefined, dateModified: (_v = (_u = dateToIso(article.updatedAt)) !== null && _u !== void 0 ? _u : dateToIso(article.publishedAt)) !== null && _v !== void 0 ? _v : undefined, author: article.author
|
|
351
|
+
? { "@id": authorId }
|
|
352
|
+
: {
|
|
353
|
+
"@id": organizationId,
|
|
354
|
+
}, publisher: {
|
|
355
|
+
"@id": organizationId,
|
|
356
|
+
} }, (imageId ? { image: { "@id": imageId } } : {})), ((_x = (_w = article.seo) === null || _w === void 0 ? void 0 : _w.schemaOverride) !== null && _x !== void 0 ? _x : {})),
|
|
357
|
+
];
|
|
358
|
+
return {
|
|
359
|
+
"@context": "https://schema.org",
|
|
360
|
+
"@graph": graph,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
export function buildRssXml(params) {
|
|
364
|
+
var _a, _b;
|
|
365
|
+
const prefix = normalizeRoutePrefix(params.site.routePrefix);
|
|
366
|
+
const channelUrl = absoluteUrl(params.site.siteUrl, prefix || "/");
|
|
367
|
+
const items = params.articles
|
|
368
|
+
.filter((article) => !hasNoIndex(article))
|
|
369
|
+
.map((article) => {
|
|
370
|
+
var _a;
|
|
371
|
+
const url = articleCanonicalUrl(article, params.site);
|
|
372
|
+
return [
|
|
373
|
+
"<item>",
|
|
374
|
+
`<title>${escapeHtml(article.title)}</title>`,
|
|
375
|
+
`<link>${escapeHtml(url)}</link>`,
|
|
376
|
+
`<guid>${escapeHtml(url)}</guid>`,
|
|
377
|
+
article.excerpt ? `<description>${escapeHtml(article.excerpt)}</description>` : "",
|
|
378
|
+
dateToIso(article.publishedAt)
|
|
379
|
+
? `<pubDate>${new Date((_a = dateToIso(article.publishedAt)) !== null && _a !== void 0 ? _a : "").toUTCString()}</pubDate>`
|
|
380
|
+
: "",
|
|
381
|
+
"</item>",
|
|
382
|
+
].join("");
|
|
383
|
+
})
|
|
384
|
+
.join("");
|
|
385
|
+
return [
|
|
386
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
387
|
+
'<rss version="2.0">',
|
|
388
|
+
"<channel>",
|
|
389
|
+
`<title>${escapeHtml((_a = params.title) !== null && _a !== void 0 ? _a : `${params.site.siteName} Blog`)}</title>`,
|
|
390
|
+
`<link>${escapeHtml(channelUrl)}</link>`,
|
|
391
|
+
`<description>${escapeHtml((_b = params.description) !== null && _b !== void 0 ? _b : `${params.site.siteName} articles`)}</description>`,
|
|
392
|
+
items,
|
|
393
|
+
"</channel>",
|
|
394
|
+
"</rss>",
|
|
395
|
+
].join("");
|
|
396
|
+
}
|
|
397
|
+
export function buildBlogSitemapEntries(site, articles) {
|
|
398
|
+
return articles
|
|
399
|
+
.filter((article) => isIndexableBlogArticle(article, site))
|
|
400
|
+
.map((article) => {
|
|
401
|
+
var _a, _b;
|
|
402
|
+
return ({
|
|
403
|
+
url: articleCanonicalUrl(article, site),
|
|
404
|
+
lastModified: (_b = (_a = dateToIso(article.updatedAt)) !== null && _a !== void 0 ? _a : dateToIso(article.publishedAt)) !== null && _b !== void 0 ? _b : undefined,
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
export function buildBlogPaginatedSitemapEntries(site, basePath, totalDocs = 0, pageSize = 12) {
|
|
409
|
+
const safePageSize = Math.max(1, Math.floor(pageSize));
|
|
410
|
+
const totalPages = Math.max(1, Math.ceil(totalDocs / safePageSize));
|
|
411
|
+
const normalizedBase = basePath.replace(/\/$/, "") || "/";
|
|
412
|
+
return Array.from({ length: totalPages }, (_, index) => ({
|
|
413
|
+
url: absoluteUrl(site.siteUrl, index === 0 ? normalizedBase : `${normalizedBase}/page/${index + 1}`),
|
|
414
|
+
}));
|
|
415
|
+
}
|
|
416
|
+
export function buildBlogIndexSitemapEntries(site, totalPages = 1) {
|
|
417
|
+
return Array.from({ length: Math.max(1, totalPages) }, (_, index) => ({
|
|
418
|
+
url: absoluteUrl(site.siteUrl, blogIndexPath(site, index + 1)),
|
|
419
|
+
}));
|
|
420
|
+
}
|
|
421
|
+
export function buildBlogDirectorySitemapEntries(site) {
|
|
422
|
+
const prefix = normalizeRoutePrefix(site.routePrefix);
|
|
423
|
+
return ["authors", "categories", "tags"].map((segment) => ({
|
|
424
|
+
url: absoluteUrl(site.siteUrl, `${prefix}/${segment}`),
|
|
425
|
+
}));
|
|
426
|
+
}
|
|
427
|
+
export function buildBlogAuthorSitemapEntries(site, authors) {
|
|
428
|
+
return authors.flatMap((author) => author.slug
|
|
429
|
+
? [
|
|
430
|
+
{
|
|
431
|
+
url: absoluteUrl(site.siteUrl, authorPath(author, site)),
|
|
432
|
+
},
|
|
433
|
+
]
|
|
434
|
+
: []);
|
|
435
|
+
}
|
|
436
|
+
export function buildBlogCategorySitemapEntries(site, categories) {
|
|
437
|
+
return categories.map((category) => ({
|
|
438
|
+
url: absoluteUrl(site.siteUrl, categoryPath(category, site)),
|
|
439
|
+
}));
|
|
440
|
+
}
|
|
441
|
+
export function buildBlogTagSitemapEntries(site, tags) {
|
|
442
|
+
return tags.map((tag) => ({
|
|
443
|
+
url: absoluteUrl(site.siteUrl, tagPath(tag, site)),
|
|
444
|
+
}));
|
|
445
|
+
}
|
|
446
|
+
export function buildSitemapUrlsetXml(entries) {
|
|
447
|
+
const urls = entries
|
|
448
|
+
.map((entry) => [
|
|
449
|
+
"<url>",
|
|
450
|
+
`<loc>${escapeHtml(entry.url)}</loc>`,
|
|
451
|
+
entry.lastModified
|
|
452
|
+
? `<lastmod>${escapeHtml(entry.lastModified)}</lastmod>`
|
|
453
|
+
: "",
|
|
454
|
+
"</url>",
|
|
455
|
+
].join(""))
|
|
456
|
+
.join("");
|
|
457
|
+
return [
|
|
458
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
459
|
+
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
460
|
+
urls,
|
|
461
|
+
"</urlset>",
|
|
462
|
+
].join("");
|
|
463
|
+
}
|
|
464
|
+
export function buildSitemapIndexXml(entries) {
|
|
465
|
+
const sitemaps = entries
|
|
466
|
+
.map((entry) => [
|
|
467
|
+
"<sitemap>",
|
|
468
|
+
`<loc>${escapeHtml(entry.url)}</loc>`,
|
|
469
|
+
entry.lastModified
|
|
470
|
+
? `<lastmod>${escapeHtml(entry.lastModified)}</lastmod>`
|
|
471
|
+
: "",
|
|
472
|
+
"</sitemap>",
|
|
473
|
+
].join(""))
|
|
474
|
+
.join("");
|
|
475
|
+
return [
|
|
476
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
477
|
+
'<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
478
|
+
sitemaps,
|
|
479
|
+
"</sitemapindex>",
|
|
480
|
+
].join("");
|
|
481
|
+
}
|
|
482
|
+
export function buildBlogRobots(site) {
|
|
483
|
+
return {
|
|
484
|
+
rules: {
|
|
485
|
+
userAgent: "*",
|
|
486
|
+
allow: normalizeRoutePrefix(site.routePrefix) || "/",
|
|
487
|
+
},
|
|
488
|
+
sitemap: absoluteUrl(site.siteUrl, "/sitemap.xml"),
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
export function searchBlogArticles(articles, query, limit = 20) {
|
|
492
|
+
const terms = query
|
|
493
|
+
.trim()
|
|
494
|
+
.toLowerCase()
|
|
495
|
+
.split(/\s+/)
|
|
496
|
+
.filter(Boolean);
|
|
497
|
+
if (terms.length === 0)
|
|
498
|
+
return [];
|
|
499
|
+
return articles
|
|
500
|
+
.map((article) => {
|
|
501
|
+
var _a, _b, _c;
|
|
502
|
+
const haystack = [
|
|
503
|
+
article.title,
|
|
504
|
+
article.excerpt,
|
|
505
|
+
article.searchText,
|
|
506
|
+
(_a = article.author) === null || _a === void 0 ? void 0 : _a.name,
|
|
507
|
+
...((_b = article.categories) !== null && _b !== void 0 ? _b : []).map((category) => category.title),
|
|
508
|
+
...((_c = article.tags) !== null && _c !== void 0 ? _c : []).map((tag) => tag.title),
|
|
509
|
+
]
|
|
510
|
+
.filter(Boolean)
|
|
511
|
+
.join(" ")
|
|
512
|
+
.toLowerCase();
|
|
513
|
+
const score = terms.reduce((total, term) => total + (haystack.includes(term) ? 1 : 0), 0);
|
|
514
|
+
return { article, score };
|
|
515
|
+
})
|
|
516
|
+
.filter((entry) => entry.score > 0)
|
|
517
|
+
.sort((a, b) => b.score - a.score)
|
|
518
|
+
.slice(0, limit)
|
|
519
|
+
.map((entry) => entry.article);
|
|
520
|
+
}
|
|
521
|
+
async function payloadFetch(options, path) {
|
|
522
|
+
var _a;
|
|
523
|
+
const fetchImpl = (_a = options.fetchImpl) !== null && _a !== void 0 ? _a : fetch;
|
|
524
|
+
const response = await fetchImpl(absoluteUrl(options.baseUrl, path), { headers: options.headers });
|
|
525
|
+
if (!response.ok) {
|
|
526
|
+
throw new Error(`Payload request failed: ${response.status} ${response.statusText}`);
|
|
527
|
+
}
|
|
528
|
+
return (await response.json());
|
|
529
|
+
}
|
|
530
|
+
export async function fetchPayloadBlogPosts(options) {
|
|
531
|
+
var _a, _b, _c;
|
|
532
|
+
const collection = (_a = options.postsCollection) !== null && _a !== void 0 ? _a : "blog-posts";
|
|
533
|
+
const params = new URLSearchParams({
|
|
534
|
+
depth: "2",
|
|
535
|
+
sort: "-publishedAt",
|
|
536
|
+
limit: String((_b = options.limit) !== null && _b !== void 0 ? _b : 20),
|
|
537
|
+
page: String((_c = options.page) !== null && _c !== void 0 ? _c : 1),
|
|
538
|
+
"where[_status][equals]": "published",
|
|
539
|
+
});
|
|
540
|
+
const result = await payloadFetch(options, `/api/${collection}?${params.toString()}`);
|
|
541
|
+
return normalizePayloadBlogListResult(result);
|
|
542
|
+
}
|
|
543
|
+
export async function fetchAllPayloadBlogPosts(options) {
|
|
544
|
+
var _a, _b, _c;
|
|
545
|
+
const limit = (_a = options.limit) !== null && _a !== void 0 ? _a : 100;
|
|
546
|
+
let page = 1;
|
|
547
|
+
let totalPages = 1;
|
|
548
|
+
const docs = [];
|
|
549
|
+
let latest = null;
|
|
550
|
+
do {
|
|
551
|
+
latest = await fetchPayloadBlogPosts(Object.assign(Object.assign({}, options), { limit, page }));
|
|
552
|
+
docs.push(...latest.docs);
|
|
553
|
+
totalPages = (_b = latest.totalPages) !== null && _b !== void 0 ? _b : page;
|
|
554
|
+
page += 1;
|
|
555
|
+
} while (page <= totalPages);
|
|
556
|
+
return Object.assign(Object.assign({}, (latest !== null && latest !== void 0 ? latest : {})), { docs, page: 1, totalDocs: (_c = latest === null || latest === void 0 ? void 0 : latest.totalDocs) !== null && _c !== void 0 ? _c : docs.length, totalPages });
|
|
557
|
+
}
|
|
558
|
+
async function fetchPayloadCollectionDocs(options) {
|
|
559
|
+
var _a, _b, _c, _d;
|
|
560
|
+
const limit = (_a = options.limit) !== null && _a !== void 0 ? _a : 100;
|
|
561
|
+
let page = 1;
|
|
562
|
+
let totalPages = 1;
|
|
563
|
+
const docs = [];
|
|
564
|
+
let latest = null;
|
|
565
|
+
do {
|
|
566
|
+
const params = new URLSearchParams({
|
|
567
|
+
depth: "2",
|
|
568
|
+
limit: String(limit),
|
|
569
|
+
page: String(page),
|
|
570
|
+
sort: (_b = options.sort) !== null && _b !== void 0 ? _b : "title",
|
|
571
|
+
});
|
|
572
|
+
latest = await payloadFetch(options, `/api/${options.collection}?${params.toString()}`);
|
|
573
|
+
docs.push(...latest.docs);
|
|
574
|
+
totalPages = (_c = latest.totalPages) !== null && _c !== void 0 ? _c : page;
|
|
575
|
+
page += 1;
|
|
576
|
+
} while (page <= totalPages);
|
|
577
|
+
return Object.assign(Object.assign({}, (latest !== null && latest !== void 0 ? latest : {})), { docs: docs.map(options.normalize), page: 1, totalDocs: (_d = latest === null || latest === void 0 ? void 0 : latest.totalDocs) !== null && _d !== void 0 ? _d : docs.length, totalPages });
|
|
578
|
+
}
|
|
579
|
+
async function fetchPayloadCollectionDocBySlug(options) {
|
|
580
|
+
const params = new URLSearchParams({
|
|
581
|
+
depth: "2",
|
|
582
|
+
limit: "1",
|
|
583
|
+
"where[slug][equals]": options.slug,
|
|
584
|
+
});
|
|
585
|
+
const result = await payloadFetch(options, `/api/${options.collection}?${params.toString()}`);
|
|
586
|
+
return result.docs[0] ? options.normalize(result.docs[0]) : null;
|
|
587
|
+
}
|
|
588
|
+
export function fetchPayloadBlogAuthors(options) {
|
|
589
|
+
var _a;
|
|
590
|
+
return fetchPayloadCollectionDocs(Object.assign(Object.assign({}, options), { collection: (_a = options.authorsCollection) !== null && _a !== void 0 ? _a : "blog-authors", normalize: normalizePayloadBlogAuthor, limit: options.limit, sort: "name" }));
|
|
591
|
+
}
|
|
592
|
+
export function fetchPayloadBlogAuthorBySlug(options) {
|
|
593
|
+
var _a;
|
|
594
|
+
return fetchPayloadCollectionDocBySlug(Object.assign(Object.assign({}, options), { collection: (_a = options.authorsCollection) !== null && _a !== void 0 ? _a : "blog-authors", normalize: normalizePayloadBlogAuthor }));
|
|
595
|
+
}
|
|
596
|
+
export function fetchPayloadBlogCategories(options) {
|
|
597
|
+
var _a;
|
|
598
|
+
return fetchPayloadCollectionDocs(Object.assign(Object.assign({}, options), { collection: (_a = options.categoriesCollection) !== null && _a !== void 0 ? _a : "blog-categories", normalize: normalizePayloadBlogTaxonomy, limit: options.limit, sort: "title" }));
|
|
599
|
+
}
|
|
600
|
+
export function fetchPayloadBlogCategoryBySlug(options) {
|
|
601
|
+
var _a;
|
|
602
|
+
return fetchPayloadCollectionDocBySlug(Object.assign(Object.assign({}, options), { collection: (_a = options.categoriesCollection) !== null && _a !== void 0 ? _a : "blog-categories", normalize: normalizePayloadBlogTaxonomy }));
|
|
603
|
+
}
|
|
604
|
+
export function fetchPayloadBlogTags(options) {
|
|
605
|
+
var _a;
|
|
606
|
+
return fetchPayloadCollectionDocs(Object.assign(Object.assign({}, options), { collection: (_a = options.tagsCollection) !== null && _a !== void 0 ? _a : "blog-tags", normalize: normalizePayloadBlogTaxonomy, limit: options.limit, sort: "title" }));
|
|
607
|
+
}
|
|
608
|
+
export function fetchPayloadBlogTagBySlug(options) {
|
|
609
|
+
var _a;
|
|
610
|
+
return fetchPayloadCollectionDocBySlug(Object.assign(Object.assign({}, options), { collection: (_a = options.tagsCollection) !== null && _a !== void 0 ? _a : "blog-tags", normalize: normalizePayloadBlogTaxonomy }));
|
|
611
|
+
}
|
|
612
|
+
function idEquals(left, right) {
|
|
613
|
+
return String(left) === String(right);
|
|
614
|
+
}
|
|
615
|
+
export function filterBlogArticlesByAuthor(articles, author) {
|
|
616
|
+
return articles.filter((article) => {
|
|
617
|
+
if (!article.author)
|
|
618
|
+
return false;
|
|
619
|
+
if (author.id != null && article.author.id != null) {
|
|
620
|
+
return idEquals(article.author.id, author.id);
|
|
621
|
+
}
|
|
622
|
+
return Boolean(author.slug && article.author.slug === author.slug);
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
export function filterBlogArticlesByCategory(articles, category) {
|
|
626
|
+
return articles.filter((article) => {
|
|
627
|
+
var _a;
|
|
628
|
+
return ((_a = article.categories) !== null && _a !== void 0 ? _a : []).some((item) => {
|
|
629
|
+
if (category.id != null && item.id != null)
|
|
630
|
+
return idEquals(item.id, category.id);
|
|
631
|
+
return item.slug === category.slug;
|
|
632
|
+
});
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
export function filterBlogArticlesByTag(articles, tag) {
|
|
636
|
+
return articles.filter((article) => {
|
|
637
|
+
var _a;
|
|
638
|
+
return ((_a = article.tags) !== null && _a !== void 0 ? _a : []).some((item) => {
|
|
639
|
+
if (tag.id != null && item.id != null)
|
|
640
|
+
return idEquals(item.id, tag.id);
|
|
641
|
+
return item.slug === tag.slug;
|
|
642
|
+
});
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
export async function fetchPayloadBlogPostBySlug(options) {
|
|
646
|
+
var _a;
|
|
647
|
+
const collection = (_a = options.postsCollection) !== null && _a !== void 0 ? _a : "blog-posts";
|
|
648
|
+
const params = new URLSearchParams({
|
|
649
|
+
depth: "2",
|
|
650
|
+
limit: "1",
|
|
651
|
+
"where[slug][equals]": options.slug,
|
|
652
|
+
"where[_status][equals]": "published",
|
|
653
|
+
});
|
|
654
|
+
const result = await payloadFetch(options, `/api/${collection}?${params.toString()}`);
|
|
655
|
+
return result.docs[0] ? normalizePayloadBlogArticle(result.docs[0]) : null;
|
|
656
|
+
}
|
|
657
|
+
export async function fetchPayloadBlogPostByPreviousSlug(options) {
|
|
658
|
+
var _a;
|
|
659
|
+
const collection = (_a = options.postsCollection) !== null && _a !== void 0 ? _a : "blog-posts";
|
|
660
|
+
const params = new URLSearchParams({
|
|
661
|
+
depth: "2",
|
|
662
|
+
limit: "1",
|
|
663
|
+
"where[slugHistory.slug][equals]": options.slug,
|
|
664
|
+
"where[_status][equals]": "published",
|
|
665
|
+
});
|
|
666
|
+
const result = await payloadFetch(options, `/api/${collection}?${params.toString()}`);
|
|
667
|
+
return result.docs[0] ? normalizePayloadBlogArticle(result.docs[0]) : null;
|
|
668
|
+
}
|
|
669
|
+
export async function fetchPayloadBlogRedirect(options) {
|
|
670
|
+
var _a, _b;
|
|
671
|
+
const collection = (_a = options.redirectsCollection) !== null && _a !== void 0 ? _a : "blog-redirects";
|
|
672
|
+
const params = new URLSearchParams({
|
|
673
|
+
depth: "1",
|
|
674
|
+
limit: "1",
|
|
675
|
+
"where[from][equals]": options.path,
|
|
676
|
+
});
|
|
677
|
+
const result = await payloadFetch(options, `/api/${collection}?${params.toString()}`);
|
|
678
|
+
return (_b = result.docs[0]) !== null && _b !== void 0 ? _b : null;
|
|
679
|
+
}
|
|
680
|
+
export { absoluteUrl, articlePath, articleUrl, authorPath, blogIndexPath, categoryPath, normalizeRoutePrefix, tagPath, };
|
|
681
|
+
//# sourceMappingURL=server.js.map
|