@roottale/cms-renderer-next 0.48.0 → 0.51.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 +56 -0
- package/dist/blog-filter-BKCGM0qd.d.ts +29 -0
- package/dist/{chunk-6MFHA555.js → chunk-27RT6B3O.js} +1 -1
- package/dist/chunk-27RT6B3O.js.map +1 -0
- package/dist/chunk-2QU4JU46.js +3927 -0
- package/dist/chunk-2QU4JU46.js.map +1 -0
- package/dist/chunk-4RQ3SEDL.js +106 -0
- package/dist/chunk-4RQ3SEDL.js.map +1 -0
- package/dist/{chunk-OMXEU4LS.js → chunk-QYNEOFL7.js} +140 -136
- package/dist/chunk-QYNEOFL7.js.map +1 -0
- package/dist/concerns-client.d.ts +1 -1
- package/dist/expertise-client.d.ts +1 -1
- package/dist/expertise-client.js +1 -1
- package/dist/hero-carousel-client.js +1 -1
- package/dist/routes.d.ts +334 -20
- package/dist/routes.js +249 -68
- package/dist/routes.js.map +1 -1
- package/dist/seo-asset-hosts.d.ts +36 -0
- package/dist/seo-asset-hosts.js +391 -0
- package/dist/seo-asset-hosts.js.map +1 -0
- package/dist/server.d.ts +23 -241
- package/dist/server.js +6 -6
- package/dist/{site-config-Dicv57oY.d.ts → site-config-DNpvlqA5.d.ts} +201 -201
- package/dist/spaces-client.d.ts +1 -1
- package/dist/team-expanding-stage-client.d.ts +1 -1
- package/dist/team-expanding-stage-client.js +1 -1
- package/dist/templates.d.ts +64 -25
- package/dist/templates.js +13 -6
- package/dist/templates.js.map +1 -1
- package/package.json +7 -2
- package/dist/chunk-6MFHA555.js.map +0 -1
- package/dist/chunk-FZK3EXYZ.js +0 -103
- package/dist/chunk-FZK3EXYZ.js.map +0 -1
- package/dist/chunk-LIBSVC4M.js +0 -3642
- package/dist/chunk-LIBSVC4M.js.map +0 -1
- package/dist/chunk-OMXEU4LS.js.map +0 -1
package/dist/routes.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
collectCategoriesWithCounts,
|
|
3
3
|
collectCollectionCategories,
|
|
4
4
|
resolveCollections,
|
|
5
5
|
resolveCollectionsResult,
|
|
@@ -14,20 +14,21 @@ import { CMS_CLIENT_VERSION } from "@roottale/cms-client/server";
|
|
|
14
14
|
|
|
15
15
|
// src/routes-feed-sitemap.ts
|
|
16
16
|
import {
|
|
17
|
-
fetchAuthors,
|
|
18
|
-
fetchBlogSettings,
|
|
19
|
-
fetchPosts,
|
|
20
17
|
generateRssXml,
|
|
21
18
|
rssItemsFromPosts
|
|
22
19
|
} from "@roottale/cms-client/server";
|
|
23
20
|
import {
|
|
24
|
-
isInCollectionMode,
|
|
25
|
-
resolvePostCollection as
|
|
26
|
-
resolvePostUrl as
|
|
21
|
+
isInCollectionMode as isInCollectionMode2,
|
|
22
|
+
resolvePostCollection as resolvePostCollection3,
|
|
23
|
+
resolvePostUrl as resolvePostUrl3
|
|
27
24
|
} from "@roottale/cms-core";
|
|
28
25
|
|
|
29
26
|
// src/routes-metadata.ts
|
|
30
27
|
import { resolvePostPath } from "@roottale/cms-core";
|
|
28
|
+
function resolveRobotsMeta(flags) {
|
|
29
|
+
if (!flags.noindex && !flags.nofollow) return void 0;
|
|
30
|
+
return { index: !flags.noindex, follow: !flags.nofollow };
|
|
31
|
+
}
|
|
31
32
|
function buildPostMetadata(post, options = {}) {
|
|
32
33
|
const seo = post.seo ?? void 0;
|
|
33
34
|
const title = seo?.title || post.title;
|
|
@@ -79,9 +80,11 @@ function buildPostMetadata(post, options = {}) {
|
|
|
79
80
|
}
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
const robots = resolveRobotsMeta({
|
|
84
|
+
...seo?.noindex !== void 0 && { noindex: seo.noindex },
|
|
85
|
+
...seo?.nofollow !== void 0 && { nofollow: seo.nofollow }
|
|
86
|
+
});
|
|
87
|
+
if (robots) meta.robots = robots;
|
|
85
88
|
if (post.id) meta.other = { "rt:content-id": post.id };
|
|
86
89
|
const twitter = { card: "summary_large_image", title };
|
|
87
90
|
if (description) twitter.description = description;
|
|
@@ -106,40 +109,133 @@ function buildHreflangLanguages(translations, siteUrl, locales) {
|
|
|
106
109
|
return languages;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
// src/
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
112
|
+
// src/archive-index-policy.ts
|
|
113
|
+
var ARCHIVE_POST_COUNT_LIMIT = 200;
|
|
114
|
+
var NOT_FOUND = {
|
|
115
|
+
render: "notFound",
|
|
116
|
+
index: false,
|
|
117
|
+
inSitemap: false
|
|
118
|
+
};
|
|
119
|
+
var NOINDEX = {
|
|
120
|
+
render: "ok",
|
|
121
|
+
index: false,
|
|
122
|
+
inSitemap: false
|
|
123
|
+
};
|
|
124
|
+
var INDEXED = {
|
|
125
|
+
render: "ok",
|
|
126
|
+
index: true,
|
|
127
|
+
inSitemap: true
|
|
128
|
+
};
|
|
129
|
+
var POLICY_NOT_APPLIED = INDEXED;
|
|
130
|
+
function isNonNegativeInteger(value) {
|
|
131
|
+
return Number.isInteger(value) && value >= 0;
|
|
132
|
+
}
|
|
133
|
+
function resolveCategoryPromotion(promotedSlugs, slug) {
|
|
134
|
+
if (!promotedSlugs) return "unknown";
|
|
135
|
+
return promotedSlugs.includes(slug) ? "promoted" : "not-promoted";
|
|
136
|
+
}
|
|
137
|
+
function resolveAuthorPromotion(authorsEnabled) {
|
|
138
|
+
if (authorsEnabled === void 0) return "unknown";
|
|
139
|
+
return authorsEnabled ? "promoted" : "not-promoted";
|
|
140
|
+
}
|
|
141
|
+
function decideArchiveIndex(input) {
|
|
142
|
+
const page = input.page ?? 1;
|
|
143
|
+
if (!isNonNegativeInteger(input.postCount)) return NOINDEX;
|
|
144
|
+
if (!isNonNegativeInteger(page) || page < 1) return NOINDEX;
|
|
145
|
+
if (input.postCount === 0 && input.kind !== "search") return NOT_FOUND;
|
|
146
|
+
if (page >= 2) return NOINDEX;
|
|
147
|
+
if (input.kind !== "category" && input.kind !== "author") return NOINDEX;
|
|
148
|
+
switch (input.promotion) {
|
|
149
|
+
case "promoted":
|
|
150
|
+
return INDEXED;
|
|
151
|
+
case "unknown":
|
|
152
|
+
return POLICY_NOT_APPLIED;
|
|
153
|
+
default:
|
|
154
|
+
return NOINDEX;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function buildArchiveMetadata(input, options = {}) {
|
|
158
|
+
const decision = decideArchiveIndex(input);
|
|
159
|
+
const meta = { title: input.title };
|
|
160
|
+
if (input.description) meta.description = input.description;
|
|
161
|
+
if (options.siteUrl && options.path) {
|
|
162
|
+
const normalized = options.path.startsWith("/") ? options.path : `/${options.path}`;
|
|
163
|
+
meta.alternates = { canonical: `${trimSlash(options.siteUrl)}${normalized}` };
|
|
164
|
+
}
|
|
165
|
+
const robots = resolveRobotsMeta({
|
|
166
|
+
noindex: !decision.index,
|
|
167
|
+
...input.nofollow !== void 0 && { nofollow: input.nofollow }
|
|
168
|
+
});
|
|
169
|
+
if (robots) meta.robots = robots;
|
|
170
|
+
return meta;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/routes-sitemap-entries.ts
|
|
174
|
+
import {
|
|
175
|
+
fetchAuthors,
|
|
176
|
+
fetchBlogSettings,
|
|
177
|
+
fetchPosts as fetchPosts2
|
|
178
|
+
} from "@roottale/cms-client/server";
|
|
179
|
+
import { isInCollectionMode, resolvePostCollection as resolvePostCollection2, resolvePostUrl as resolvePostUrl2 } from "@roottale/cms-core";
|
|
180
|
+
|
|
181
|
+
// src/archive-categories.ts
|
|
182
|
+
import {
|
|
183
|
+
fetchCategoryCounts,
|
|
184
|
+
fetchPosts
|
|
185
|
+
} from "@roottale/cms-client/server";
|
|
186
|
+
async function fetchBlogArchivePosts(config, options = {}) {
|
|
187
|
+
const page = await fetchPosts({
|
|
188
|
+
apiKey: config.apiKey,
|
|
189
|
+
baseUrl: config.apiBase,
|
|
190
|
+
type: "post",
|
|
191
|
+
limit: ARCHIVE_POST_COUNT_LIMIT,
|
|
192
|
+
// 서버측 "미소속 글" 필터 — 페이지(`excludeCollections`)와 같은 정의.
|
|
193
|
+
excludeCollections: true,
|
|
194
|
+
...options.revalidate !== void 0 && { revalidate: options.revalidate }
|
|
195
|
+
});
|
|
196
|
+
return page.items;
|
|
197
|
+
}
|
|
198
|
+
async function fetchServerCategoryCounts(config, options) {
|
|
199
|
+
try {
|
|
200
|
+
const result = await fetchCategoryCounts({
|
|
201
|
+
apiKey: config.apiKey,
|
|
202
|
+
baseUrl: config.apiBase,
|
|
203
|
+
// 레거시 `/blog` 계열의 모집단 = 미소속 글. 페이지(`excludeCollections`)·
|
|
204
|
+
// 사이트맵과 **같은 서버 판정**을 쓰기 위해 서버 필터로 지정한다.
|
|
205
|
+
excludeCollections: true,
|
|
206
|
+
...options.revalidate !== void 0 && { revalidate: options.revalidate }
|
|
136
207
|
});
|
|
137
|
-
|
|
208
|
+
if (result.truncated) {
|
|
209
|
+
console.warn(
|
|
210
|
+
"[@roottale/cms-renderer-next/routes] \uBD84\uB958 \uC218\uAC00 \uC11C\uBC84 \uC0C1\uD55C\uC744 \uB118\uC5B4 \uC77C\uBD80\uAC00 \uC751\uB2F5\uC5D0\uC11C \uBE60\uC84C\uC2B5\uB2C8\uB2E4(\uC0C9\uC778\uC5D0\uC11C \uB204\uB77D\uB420 \uC218 \uC788\uC74C)."
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
return result.categories.filter((category) => category.publishedPostCount > 0).map((category) => ({
|
|
214
|
+
name: category.name,
|
|
215
|
+
slug: category.slug,
|
|
216
|
+
count: category.publishedPostCount
|
|
217
|
+
}));
|
|
218
|
+
} catch (err) {
|
|
219
|
+
console.warn(
|
|
220
|
+
"[@roottale/cms-renderer-next/routes] \uBD84\uB958\uBCC4 \uAE00 \uC218 \uC9D1\uACC4 API \uC2E4\uD328 \u2014 \uCD5C\uADFC \uAE00 \uBC30\uCE58 \uD30C\uC0DD\uC73C\uB85C \uD3F4\uBC31:",
|
|
221
|
+
err
|
|
222
|
+
);
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async function fetchBlogArchiveCategories(config, options = {}) {
|
|
227
|
+
const counts = await fetchServerCategoryCounts(config, options);
|
|
228
|
+
if (counts) return counts;
|
|
229
|
+
return collectCategoriesWithCounts(await fetchBlogArchivePosts(config, options));
|
|
138
230
|
}
|
|
231
|
+
|
|
232
|
+
// src/routes-sitemap-entries.ts
|
|
139
233
|
var SITEMAP_DEFAULTS = {
|
|
140
234
|
blogImages: true,
|
|
141
235
|
locales: [],
|
|
142
236
|
authors: false
|
|
237
|
+
// promotedCategorySlugs 는 의도적으로 기본값이 없다 — "모름"(undefined)과
|
|
238
|
+
// "승격 0건"([])을 구분해야 색인 정책을 fail-soft 로 적용할 수 있다.
|
|
143
239
|
};
|
|
144
240
|
async function safeFetchAuthors(config) {
|
|
145
241
|
try {
|
|
@@ -151,27 +247,36 @@ async function safeFetchAuthors(config) {
|
|
|
151
247
|
}
|
|
152
248
|
async function resolveSitemapSettings(config, opts) {
|
|
153
249
|
let remote = {};
|
|
250
|
+
let settingsFetchFailed = false;
|
|
154
251
|
if (!opts.skipRemoteSettings) {
|
|
155
252
|
try {
|
|
156
253
|
remote = (await fetchBlogSettings({
|
|
157
254
|
apiKey: config.apiKey,
|
|
158
255
|
baseUrl: config.apiBase
|
|
159
256
|
})).sitemap ?? {};
|
|
160
|
-
} catch {
|
|
257
|
+
} catch (err) {
|
|
258
|
+
settingsFetchFailed = true;
|
|
259
|
+
console.error(
|
|
260
|
+
"[@roottale/cms-renderer-next/routes] fetchBlogSettings \uC2E4\uD328(\uAE30\uBCF8\uAC12\uC73C\uB85C \uC9C4\uD589):",
|
|
261
|
+
err
|
|
262
|
+
);
|
|
161
263
|
}
|
|
162
264
|
}
|
|
163
|
-
|
|
265
|
+
const settings = {
|
|
164
266
|
blogImages: opts.blogImages ?? remote.blogImages ?? SITEMAP_DEFAULTS.blogImages,
|
|
165
267
|
locales: opts.locales ?? remote.locales ?? SITEMAP_DEFAULTS.locales,
|
|
166
268
|
authors: opts.authors ?? remote.authors ?? SITEMAP_DEFAULTS.authors
|
|
167
269
|
};
|
|
270
|
+
const promoted = opts.promotedCategorySlugs ?? remote.promotedCategorySlugs;
|
|
271
|
+
if (promoted) settings.promotedCategorySlugs = promoted;
|
|
272
|
+
return { settings, settingsFetchFailed };
|
|
168
273
|
}
|
|
169
274
|
async function localesWithPublishedContent(config, locales) {
|
|
170
275
|
if (locales.length === 0) return locales;
|
|
171
276
|
const checks = await Promise.all(
|
|
172
277
|
locales.map(async (locale) => {
|
|
173
278
|
try {
|
|
174
|
-
const page = await
|
|
279
|
+
const page = await fetchPosts2({
|
|
175
280
|
apiKey: config.apiKey,
|
|
176
281
|
baseUrl: config.apiBase,
|
|
177
282
|
type: "post",
|
|
@@ -224,84 +329,152 @@ function postEntries(config, siteUrl, posts, collections, settings, defaultLocal
|
|
|
224
329
|
return [entry];
|
|
225
330
|
});
|
|
226
331
|
}
|
|
227
|
-
function
|
|
332
|
+
async function safeBlogArchiveCategories(config) {
|
|
333
|
+
try {
|
|
334
|
+
return await fetchBlogArchiveCategories(config);
|
|
335
|
+
} catch (err) {
|
|
336
|
+
console.error(
|
|
337
|
+
"[@roottale/cms-renderer-next/routes] \uC544\uCE74\uC774\uBE0C \uCE74\uD14C\uACE0\uB9AC \uC870\uD68C \uC2E4\uD328:",
|
|
338
|
+
err
|
|
339
|
+
);
|
|
340
|
+
return [];
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
async function categoryEntries(config, siteUrl, collections, promotedSlugs) {
|
|
344
|
+
const inSitemap = (category) => decideArchiveIndex({
|
|
345
|
+
kind: "category",
|
|
346
|
+
promotion: resolveCategoryPromotion(promotedSlugs, category.slug),
|
|
347
|
+
postCount: category.count
|
|
348
|
+
}).inSitemap;
|
|
228
349
|
if (isInCollectionMode(collections)) {
|
|
350
|
+
const posts = await safeFetchPosts(config, ARCHIVE_POST_COUNT_LIMIT);
|
|
229
351
|
return collections.filter((c) => c.archives && c.basePath).flatMap((c) => {
|
|
230
352
|
const cats = collectCollectionCategories(posts, collections, c.key);
|
|
231
353
|
if (!cats.length) return [];
|
|
232
354
|
const base = `${siteUrl}${trimSlash(c.basePath)}`;
|
|
233
355
|
return [
|
|
234
356
|
{ url: `${base}/categories` },
|
|
235
|
-
...cats.map((category) => ({
|
|
357
|
+
...cats.filter(inSitemap).map((category) => ({
|
|
236
358
|
url: `${base}/categories/${category.slug}`
|
|
237
359
|
}))
|
|
238
360
|
];
|
|
239
361
|
});
|
|
240
362
|
}
|
|
241
|
-
const categories =
|
|
363
|
+
const categories = await safeBlogArchiveCategories(config);
|
|
242
364
|
if (!categories.length) return [];
|
|
243
365
|
const blogBase = config.blogBasePath ?? "/blog";
|
|
244
366
|
return [
|
|
245
367
|
{ url: `${siteUrl}${blogBase}/categories` },
|
|
246
|
-
...categories.map((category) => ({
|
|
368
|
+
...categories.filter(inSitemap).map((category) => ({
|
|
247
369
|
url: `${siteUrl}${blogBase}/categories/${category.slug}`
|
|
248
370
|
}))
|
|
249
371
|
];
|
|
250
372
|
}
|
|
373
|
+
async function authorEntries(config, siteUrl, settings, authorBasePath) {
|
|
374
|
+
if (!settings.authors) return [];
|
|
375
|
+
const authors = await safeFetchAuthors(config);
|
|
376
|
+
const base = trimSlash(authorBasePath ?? "/blog/author");
|
|
377
|
+
const promotion = resolveAuthorPromotion(settings.authors);
|
|
378
|
+
return authors.filter(
|
|
379
|
+
(a) => decideArchiveIndex({
|
|
380
|
+
kind: "author",
|
|
381
|
+
promotion,
|
|
382
|
+
postCount: a.postCount
|
|
383
|
+
}).inSitemap
|
|
384
|
+
).map((a) => ({
|
|
385
|
+
url: `${siteUrl}${base}/${encodeURIComponent(a.slug)}`,
|
|
386
|
+
lastModified: a.lastUpdatedAt ?? void 0
|
|
387
|
+
}));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// src/routes-feed-sitemap.ts
|
|
391
|
+
function createFeedRoute(config) {
|
|
392
|
+
return async function GET() {
|
|
393
|
+
const siteUrl = trimSlash(config.siteUrl);
|
|
394
|
+
const collections = await resolveCollections(config.collections);
|
|
395
|
+
const allPosts = await safeFetchPosts(config, 50);
|
|
396
|
+
const inCollectionMode = isInCollectionMode2(collections);
|
|
397
|
+
const blogBase = config.blogBasePath ?? "/blog";
|
|
398
|
+
const posts = inCollectionMode ? allPosts.filter((p) => {
|
|
399
|
+
const c = resolvePostCollection3(p, collections);
|
|
400
|
+
return c ? c.feed === true && c.detail !== false && c.basePath !== "" : false;
|
|
401
|
+
}) : allPosts;
|
|
402
|
+
const xml = generateRssXml({
|
|
403
|
+
title: config.title,
|
|
404
|
+
link: inCollectionMode ? siteUrl : `${siteUrl}${blogBase}`,
|
|
405
|
+
feedUrl: `${siteUrl}/feed.xml`,
|
|
406
|
+
description: config.description,
|
|
407
|
+
language: config.language,
|
|
408
|
+
items: rssItemsFromPosts(posts, {
|
|
409
|
+
postUrl: (p) => inCollectionMode ? resolvePostUrl3(siteUrl, p, collections) ?? `${siteUrl}${blogBase}/${p.slug}` : `${siteUrl}${blogBase}/${p.slug}`
|
|
410
|
+
})
|
|
411
|
+
});
|
|
412
|
+
return new Response(xml, {
|
|
413
|
+
headers: {
|
|
414
|
+
"content-type": "application/rss+xml; charset=utf-8",
|
|
415
|
+
"cache-control": "public, max-age=1800, s-maxage=1800"
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
};
|
|
419
|
+
}
|
|
251
420
|
function createSitemap(config, staticRoutes = []) {
|
|
252
421
|
return async function sitemap() {
|
|
253
422
|
const siteUrl = trimSlash(config.siteUrl);
|
|
254
423
|
const collections = await resolveCollections(config.collections);
|
|
255
|
-
const posts = await safeFetchPosts(config,
|
|
256
|
-
const settings = await resolveSitemapSettings(config, {
|
|
424
|
+
const posts = await safeFetchPosts(config, ARCHIVE_POST_COUNT_LIMIT);
|
|
425
|
+
const { settings } = await resolveSitemapSettings(config, {
|
|
257
426
|
skipRemoteSettings: true,
|
|
258
427
|
blogImages: false
|
|
259
428
|
});
|
|
260
429
|
return [
|
|
261
430
|
...staticEntries(staticRoutes),
|
|
262
431
|
...postEntries(config, siteUrl, posts, collections, settings),
|
|
263
|
-
|
|
432
|
+
// settings.promotedCategorySlugs 는 여기서 항상 undefined(위 skipRemoteSettings)
|
|
433
|
+
// → 색인 정책 미적용 = 레거시 동등. 정책이 필요하면 createSitemapIndex 로.
|
|
434
|
+
...await categoryEntries(config, siteUrl, collections, void 0)
|
|
264
435
|
];
|
|
265
436
|
};
|
|
266
437
|
}
|
|
267
438
|
function createSitemapIndex(config, staticRoutes = [], opts = {}) {
|
|
268
439
|
async function generateSitemaps() {
|
|
269
|
-
const settings = await resolveSitemapSettings(
|
|
440
|
+
const { settings, settingsFetchFailed } = await resolveSitemapSettings(
|
|
441
|
+
config,
|
|
442
|
+
opts
|
|
443
|
+
);
|
|
270
444
|
const ids = ["static", "blog", "categories"];
|
|
271
|
-
if (settings.authors) ids.push("authors");
|
|
445
|
+
if (settings.authors || settingsFetchFailed) ids.push("authors");
|
|
272
446
|
return ids.map((id) => ({ id }));
|
|
273
447
|
}
|
|
274
448
|
async function sitemap(props) {
|
|
275
449
|
const id = await props.id;
|
|
276
450
|
const siteUrl = trimSlash(config.siteUrl);
|
|
277
|
-
const settings = await resolveSitemapSettings(config, opts);
|
|
451
|
+
const { settings } = await resolveSitemapSettings(config, opts);
|
|
278
452
|
const activeLocales = await localesWithPublishedContent(config, settings.locales);
|
|
279
453
|
const defaultLocale = activeLocales[0];
|
|
280
454
|
if (id === "static") return staticEntries(staticRoutes);
|
|
281
455
|
if (id === "authors") {
|
|
282
|
-
|
|
283
|
-
const authors = await safeFetchAuthors(config);
|
|
284
|
-
const base = trimSlash(opts.authorBasePath ?? "/blog/author");
|
|
285
|
-
return authors.map((a) => ({
|
|
286
|
-
url: `${siteUrl}${base}/${encodeURIComponent(a.slug)}`,
|
|
287
|
-
lastModified: a.lastUpdatedAt ?? void 0
|
|
288
|
-
}));
|
|
456
|
+
return authorEntries(config, siteUrl, settings, opts.authorBasePath);
|
|
289
457
|
}
|
|
290
458
|
const collections = await resolveCollections(config.collections);
|
|
291
|
-
|
|
459
|
+
if (id === "categories") {
|
|
460
|
+
return categoryEntries(
|
|
461
|
+
config,
|
|
462
|
+
siteUrl,
|
|
463
|
+
collections,
|
|
464
|
+
settings.promotedCategorySlugs
|
|
465
|
+
);
|
|
466
|
+
}
|
|
292
467
|
if (id === "blog") {
|
|
468
|
+
const posts = await safeFetchPosts(config, ARCHIVE_POST_COUNT_LIMIT);
|
|
293
469
|
return postEntries(config, siteUrl, posts, collections, settings, defaultLocale);
|
|
294
470
|
}
|
|
295
|
-
if (id === "categories") {
|
|
296
|
-
return categoryEntries(config, siteUrl, posts, collections);
|
|
297
|
-
}
|
|
298
471
|
return [];
|
|
299
472
|
}
|
|
300
473
|
return { generateSitemaps, sitemap };
|
|
301
474
|
}
|
|
302
475
|
|
|
303
476
|
// src/routes-llms.ts
|
|
304
|
-
import { isInCollectionMode as
|
|
477
|
+
import { isInCollectionMode as isInCollectionMode3, resolvePostUrl as resolvePostUrl4 } from "@roottale/cms-core";
|
|
305
478
|
function mdLinkSafe(text) {
|
|
306
479
|
return text.replace(/[[\]()]/g, "").trim();
|
|
307
480
|
}
|
|
@@ -326,10 +499,10 @@ function createLlmsTxtRoute(config) {
|
|
|
326
499
|
}
|
|
327
500
|
}
|
|
328
501
|
if (posts.length > 0) {
|
|
329
|
-
const inCollectionMode =
|
|
502
|
+
const inCollectionMode = isInCollectionMode3(collections);
|
|
330
503
|
lines.push("", inCollectionMode ? "## \uCF58\uD150\uCE20" : "## \uBE14\uB85C\uADF8");
|
|
331
504
|
for (const p of posts) {
|
|
332
|
-
const url = inCollectionMode ?
|
|
505
|
+
const url = inCollectionMode ? resolvePostUrl4(siteUrl, p, collections) : `${siteUrl}${blogBase}/${p.slug}`;
|
|
333
506
|
if (!url) continue;
|
|
334
507
|
const excerpt = p.excerpt ? `: ${oneLine(p.excerpt)}` : "";
|
|
335
508
|
lines.push(`- [${mdLinkSafe(p.title)}](${url})${excerpt}`);
|
|
@@ -350,7 +523,7 @@ function createLlmsTxtRoute(config) {
|
|
|
350
523
|
import {
|
|
351
524
|
verifyRootTaleWebhook
|
|
352
525
|
} from "@roottale/cms-client/webhook";
|
|
353
|
-
import { isInCollectionMode as
|
|
526
|
+
import { isInCollectionMode as isInCollectionMode4 } from "@roottale/cms-core";
|
|
354
527
|
function pathsFromBody(rawBody) {
|
|
355
528
|
try {
|
|
356
529
|
const body = JSON.parse(rawBody);
|
|
@@ -406,7 +579,7 @@ function createRevalidateRoute(config) {
|
|
|
406
579
|
if (failed) {
|
|
407
580
|
alsoRevalidate = INVARIANTS;
|
|
408
581
|
warning = "collections_resolve_failed";
|
|
409
|
-
} else if (
|
|
582
|
+
} else if (isInCollectionMode4(collections)) {
|
|
410
583
|
alsoRevalidate = [
|
|
411
584
|
...INVARIANTS,
|
|
412
585
|
// 주소 없는 유형(basePath === "")은 라우트가 없으므로 revalidate 대상에서
|
|
@@ -657,7 +830,7 @@ function createFleetInfoRoute(config = {}) {
|
|
|
657
830
|
site: config.site ?? env.VERCEL_PROJECT_PRODUCTION_URL ?? null,
|
|
658
831
|
framework: "next",
|
|
659
832
|
cms_client: CMS_CLIENT_VERSION,
|
|
660
|
-
cms_renderer: true ? "0.
|
|
833
|
+
cms_renderer: true ? "0.51.0" : "dev",
|
|
661
834
|
build_sha: env.VERCEL_GIT_COMMIT_SHA?.slice(0, 7) ?? null
|
|
662
835
|
},
|
|
663
836
|
{ headers: { "cache-control": "public, max-age=300" } }
|
|
@@ -665,8 +838,10 @@ function createFleetInfoRoute(config = {}) {
|
|
|
665
838
|
};
|
|
666
839
|
}
|
|
667
840
|
export {
|
|
841
|
+
ARCHIVE_POST_COUNT_LIMIT,
|
|
668
842
|
OG_IMAGE_CONTENT_TYPE,
|
|
669
843
|
OG_IMAGE_SIZE,
|
|
844
|
+
buildArchiveMetadata,
|
|
670
845
|
buildHreflangLanguages,
|
|
671
846
|
buildPostMetadata,
|
|
672
847
|
createFeedRoute,
|
|
@@ -677,13 +852,19 @@ export {
|
|
|
677
852
|
createRevalidateRoute,
|
|
678
853
|
createSitemap,
|
|
679
854
|
createSitemapIndex,
|
|
855
|
+
decideArchiveIndex,
|
|
856
|
+
fetchBlogArchiveCategories,
|
|
857
|
+
fetchBlogArchivePosts,
|
|
680
858
|
matchRedirect,
|
|
681
859
|
normalizeRedirectPath,
|
|
682
860
|
postRedirectPath,
|
|
861
|
+
resolveAuthorPromotion,
|
|
862
|
+
resolveCategoryPromotion,
|
|
683
863
|
resolveCollections,
|
|
684
864
|
resolveCollectionsResult,
|
|
685
865
|
resolvePostCollection,
|
|
686
866
|
resolvePostUrl,
|
|
867
|
+
resolveRobotsMeta,
|
|
687
868
|
safeFetchPosts,
|
|
688
869
|
trimSlash
|
|
689
870
|
};
|