@onruntime/next-sitemap 0.6.2 → 0.8.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 +12 -0
- package/dist/app/index.cjs +200 -213
- package/dist/app/index.d.cts +11 -11
- package/dist/app/index.d.ts +11 -11
- package/dist/app/index.js +201 -210
- package/dist/index.cjs +214 -4
- package/dist/index.d.cts +65 -2
- package/dist/index.d.ts +65 -2
- package/dist/index.js +186 -5
- package/dist/loader.js +38 -0
- package/dist/pages/index.cjs +206 -205
- package/dist/pages/index.d.cts +24 -30
- package/dist/pages/index.d.ts +24 -30
- package/dist/pages/index.js +207 -202
- package/dist/worker.cjs +267 -0
- package/package.json +2 -2
package/dist/app/index.js
CHANGED
|
@@ -1,9 +1,168 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import { existsSync, readdirSync } from 'fs';
|
|
2
|
+
import { dirname, join, isAbsolute, relative, delimiter } from 'path';
|
|
3
|
+
import * as childProcess from 'child_process';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
5
|
|
|
6
6
|
// src/app/index.ts
|
|
7
|
+
var NO_STATIC_PARAMS = "NO_STATIC_PARAMS";
|
|
8
|
+
var spawnProcess = childProcess.spawn;
|
|
9
|
+
var __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
var paramsCache = /* @__PURE__ */ new Map();
|
|
11
|
+
var isDev = process.env.NODE_ENV === "development";
|
|
12
|
+
async function executeWorker(directory, fileKey, debug) {
|
|
13
|
+
const absolutePath = join(directory, fileKey.replace("./", ""));
|
|
14
|
+
const projectRoot = process.cwd();
|
|
15
|
+
const distRoot = join(__dirname$1, "..");
|
|
16
|
+
const workerPath = join(distRoot, "worker.cjs");
|
|
17
|
+
const loaderPath = join(distRoot, "loader.js");
|
|
18
|
+
if (debug) {
|
|
19
|
+
console.log(`[next-sitemap] Worker path: ${workerPath}`);
|
|
20
|
+
console.log(`[next-sitemap] Worker exists: ${existsSync(workerPath)}`);
|
|
21
|
+
console.log(`[next-sitemap] Loader path: ${loaderPath}`);
|
|
22
|
+
console.log(`[next-sitemap] Loader exists: ${existsSync(loaderPath)}`);
|
|
23
|
+
}
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
const nodePath = [
|
|
26
|
+
join(projectRoot, "node_modules"),
|
|
27
|
+
join(__dirname$1, "..", "node_modules")
|
|
28
|
+
].join(delimiter);
|
|
29
|
+
const importFlag = ["--import", loaderPath];
|
|
30
|
+
const args = [...importFlag, workerPath, absolutePath, projectRoot];
|
|
31
|
+
const child = spawnProcess("node", args, {
|
|
32
|
+
cwd: projectRoot,
|
|
33
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
34
|
+
env: { ...process.env, NODE_PATH: nodePath }
|
|
35
|
+
});
|
|
36
|
+
let stdout = "";
|
|
37
|
+
let stderr = "";
|
|
38
|
+
child.stdout.on("data", (data) => {
|
|
39
|
+
stdout += data.toString();
|
|
40
|
+
});
|
|
41
|
+
child.stderr.on("data", (data) => {
|
|
42
|
+
stderr += data.toString();
|
|
43
|
+
});
|
|
44
|
+
child.on("close", (code) => {
|
|
45
|
+
if (debug && stderr) {
|
|
46
|
+
console.warn(`[next-sitemap] Worker stderr: ${stderr}`);
|
|
47
|
+
}
|
|
48
|
+
if (code !== 0 && code !== null) {
|
|
49
|
+
if (debug) console.warn(`[next-sitemap] Worker exited with code ${code}`);
|
|
50
|
+
resolve(null);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const lines = stdout.trim().split("\n");
|
|
55
|
+
const result = JSON.parse(lines[lines.length - 1]);
|
|
56
|
+
if (result.success) {
|
|
57
|
+
resolve(result.params);
|
|
58
|
+
} else {
|
|
59
|
+
if (result.error !== NO_STATIC_PARAMS && debug) {
|
|
60
|
+
console.warn(`[next-sitemap] Worker error: ${result.error}`);
|
|
61
|
+
}
|
|
62
|
+
resolve(null);
|
|
63
|
+
}
|
|
64
|
+
} catch {
|
|
65
|
+
if (debug) console.warn(`[next-sitemap] Failed to parse worker output: ${stdout}`);
|
|
66
|
+
resolve(null);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
child.on("error", (err) => {
|
|
70
|
+
if (debug) console.warn(`[next-sitemap] Failed to spawn worker: ${err.message}`);
|
|
71
|
+
resolve(null);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function getRouteParams(route, directory, debug) {
|
|
76
|
+
const cacheKey = route.fileKey;
|
|
77
|
+
if (paramsCache.has(cacheKey)) {
|
|
78
|
+
return paramsCache.get(cacheKey);
|
|
79
|
+
}
|
|
80
|
+
if (debug) {
|
|
81
|
+
console.log(`[next-sitemap] ${route.pathname}: executing static params via worker`);
|
|
82
|
+
}
|
|
83
|
+
const params = await executeWorker(directory, route.fileKey, debug);
|
|
84
|
+
paramsCache.set(cacheKey, params);
|
|
85
|
+
if (debug && params) {
|
|
86
|
+
console.log(`[next-sitemap] ${route.pathname}: got ${params.length} params`);
|
|
87
|
+
}
|
|
88
|
+
return params;
|
|
89
|
+
}
|
|
90
|
+
async function generateAllPaths(routes, directory, debug) {
|
|
91
|
+
const staticPaths = ["/"];
|
|
92
|
+
const dynamicRoutes = [];
|
|
93
|
+
for (const route of routes) {
|
|
94
|
+
if (route.dynamicSegments.length === 0) {
|
|
95
|
+
if (route.pathname !== "/") {
|
|
96
|
+
staticPaths.push(route.pathname);
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
dynamicRoutes.push(route);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const startTime = isDev ? Date.now() : 0;
|
|
103
|
+
if (isDev && dynamicRoutes.length > 0) {
|
|
104
|
+
console.log(`[next-sitemap] Generating sitemap for ${dynamicRoutes.length} dynamic routes (dev only, instant in production)...`);
|
|
105
|
+
}
|
|
106
|
+
const dynamicResults = await Promise.all(
|
|
107
|
+
dynamicRoutes.map(async (route) => {
|
|
108
|
+
const params = await getRouteParams(route, directory, debug);
|
|
109
|
+
if (!params || params.length === 0) {
|
|
110
|
+
if (debug) {
|
|
111
|
+
console.warn(`[next-sitemap] Skipping dynamic route ${route.pathname}: no static params or empty result.`);
|
|
112
|
+
}
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
const paths = [];
|
|
116
|
+
for (const param of params) {
|
|
117
|
+
let path = route.pathname;
|
|
118
|
+
let valid = true;
|
|
119
|
+
for (const segment of route.dynamicSegments) {
|
|
120
|
+
const value = param[segment];
|
|
121
|
+
if (value === void 0) {
|
|
122
|
+
if (debug) {
|
|
123
|
+
console.warn(`[next-sitemap] ${route.pathname}: missing param "${segment}" in`, param);
|
|
124
|
+
}
|
|
125
|
+
valid = false;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
path = path.replace(`[${segment}]`, value);
|
|
129
|
+
}
|
|
130
|
+
if (valid) paths.push(path);
|
|
131
|
+
}
|
|
132
|
+
return paths;
|
|
133
|
+
})
|
|
134
|
+
);
|
|
135
|
+
const allPaths = new Set(staticPaths);
|
|
136
|
+
for (const paths of dynamicResults) {
|
|
137
|
+
for (const path of paths) {
|
|
138
|
+
allPaths.add(path);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (isDev && dynamicRoutes.length > 0) {
|
|
142
|
+
const elapsed = Date.now() - startTime;
|
|
143
|
+
console.log(`[next-sitemap] Done! Found ${allPaths.size} total URLs in ${elapsed}ms.`);
|
|
144
|
+
}
|
|
145
|
+
return Array.from(allPaths);
|
|
146
|
+
}
|
|
147
|
+
function pathsToEntries(paths, config) {
|
|
148
|
+
const { baseUrl, locales = [], defaultLocale, exclude, priority, changeFreq } = config;
|
|
149
|
+
return paths.filter((pathname) => !shouldExclude(pathname, exclude)).map((pathname) => {
|
|
150
|
+
const entry = {
|
|
151
|
+
url: buildUrl(baseUrl, pathname, defaultLocale, defaultLocale),
|
|
152
|
+
lastModified: /* @__PURE__ */ new Date(),
|
|
153
|
+
changeFrequency: getChangeFreq(pathname, changeFreq),
|
|
154
|
+
priority: getPriority(pathname, priority)
|
|
155
|
+
};
|
|
156
|
+
if (locales.length > 0) {
|
|
157
|
+
entry.alternates = {
|
|
158
|
+
languages: Object.fromEntries(
|
|
159
|
+
locales.map((locale) => [locale, buildUrl(baseUrl, pathname, locale, defaultLocale)])
|
|
160
|
+
)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return entry;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
7
166
|
|
|
8
167
|
// src/index.ts
|
|
9
168
|
function calculateDepthPriority(pathname) {
|
|
@@ -52,7 +211,8 @@ function buildUrl(baseUrl, pathname, locale, defaultLocale) {
|
|
|
52
211
|
}
|
|
53
212
|
return `${baseUrl}/${locale}${normalizedPath}`;
|
|
54
213
|
}
|
|
55
|
-
function generateSitemapXml(entries) {
|
|
214
|
+
function generateSitemapXml(entries, options) {
|
|
215
|
+
const { poweredBy = true } = options || {};
|
|
56
216
|
const hasAlternates = entries.some((e) => e.alternates?.languages);
|
|
57
217
|
const xmlns = hasAlternates ? 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"' : 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"';
|
|
58
218
|
const urlEntries = entries.map((entry) => {
|
|
@@ -76,13 +236,14 @@ function generateSitemapXml(entries) {
|
|
|
76
236
|
${parts.join("\n")}
|
|
77
237
|
</url>`;
|
|
78
238
|
}).join("\n");
|
|
79
|
-
|
|
239
|
+
const comment = poweredBy ? "\n<!-- Powered by @onruntime/next-sitemap -->" : "";
|
|
240
|
+
return `<?xml version="1.0" encoding="UTF-8"?>${comment}
|
|
80
241
|
<urlset ${xmlns}>
|
|
81
242
|
${urlEntries}
|
|
82
243
|
</urlset>`;
|
|
83
244
|
}
|
|
84
245
|
function generateSitemapIndexXml(baseUrl, sitemapCount, options) {
|
|
85
|
-
const { sitemapPattern = "/sitemap-{id}.xml", additionalSitemaps = [] } = options || {};
|
|
246
|
+
const { sitemapPattern = "/sitemap-{id}.xml", additionalSitemaps = [], poweredBy = true } = options || {};
|
|
86
247
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
87
248
|
const paginatedEntries = Array.from({ length: sitemapCount }, (_, i) => {
|
|
88
249
|
const loc = `${baseUrl}${sitemapPattern.replace("{id}", String(i))}`;
|
|
@@ -99,24 +260,24 @@ function generateSitemapIndexXml(baseUrl, sitemapCount, options) {
|
|
|
99
260
|
</sitemap>`;
|
|
100
261
|
});
|
|
101
262
|
const allEntries = [...paginatedEntries, ...additionalEntries].join("\n");
|
|
102
|
-
|
|
263
|
+
const comment = poweredBy ? "\n<!-- Powered by @onruntime/next-sitemap -->" : "";
|
|
264
|
+
return `<?xml version="1.0" encoding="UTF-8"?>${comment}
|
|
103
265
|
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
104
266
|
${allEntries}
|
|
105
267
|
</sitemapindex>`;
|
|
106
268
|
}
|
|
107
269
|
|
|
108
270
|
// src/app/index.ts
|
|
109
|
-
var joinPath = (...segments) => path.join(...segments);
|
|
110
271
|
function findPageFiles(dir, baseDir = dir) {
|
|
111
272
|
const files = [];
|
|
112
273
|
try {
|
|
113
|
-
const entries =
|
|
274
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
114
275
|
for (const entry of entries) {
|
|
115
|
-
const fullPath =
|
|
276
|
+
const fullPath = join(dir, entry.name);
|
|
116
277
|
if (entry.isDirectory()) {
|
|
117
278
|
files.push(...findPageFiles(fullPath, baseDir));
|
|
118
279
|
} else if (/^page\.(tsx?|jsx?)$/.test(entry.name)) {
|
|
119
|
-
const relativePath = "./" +
|
|
280
|
+
const relativePath = "./" + relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
120
281
|
files.push(relativePath);
|
|
121
282
|
}
|
|
122
283
|
}
|
|
@@ -124,83 +285,12 @@ function findPageFiles(dir, baseDir = dir) {
|
|
|
124
285
|
}
|
|
125
286
|
return files;
|
|
126
287
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return srcApp;
|
|
131
|
-
}
|
|
132
|
-
return path.join(process.cwd(), "app");
|
|
133
|
-
}
|
|
134
|
-
function resolveAppDirectory(options) {
|
|
135
|
-
if (options.appDirectory) {
|
|
136
|
-
return path.isAbsolute(options.appDirectory) ? options.appDirectory : path.join(process.cwd(), options.appDirectory);
|
|
288
|
+
function resolveAppDirectory(appDirectory) {
|
|
289
|
+
if (appDirectory) {
|
|
290
|
+
return isAbsolute(appDirectory) ? appDirectory : join(process.cwd(), appDirectory);
|
|
137
291
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
function getPageKeys(options) {
|
|
141
|
-
return findPageFiles(resolveAppDirectory(options));
|
|
142
|
-
}
|
|
143
|
-
var jitiCache = /* @__PURE__ */ new Map();
|
|
144
|
-
function getTsconfigPaths(projectRoot, debug = false) {
|
|
145
|
-
const alias = {};
|
|
146
|
-
try {
|
|
147
|
-
const tsconfigPath = path.join(projectRoot, "tsconfig.json");
|
|
148
|
-
if (debug) {
|
|
149
|
-
console.log("[next-sitemap] Looking for tsconfig at:", tsconfigPath);
|
|
150
|
-
console.log("[next-sitemap] tsconfig exists:", fs.existsSync(tsconfigPath));
|
|
151
|
-
}
|
|
152
|
-
if (fs.existsSync(tsconfigPath)) {
|
|
153
|
-
const content = fs.readFileSync(tsconfigPath, "utf-8");
|
|
154
|
-
const withoutComments = stripJsonComments(content);
|
|
155
|
-
const cleaned = withoutComments.replace(/,(\s*[}\]])/g, "$1");
|
|
156
|
-
if (debug) {
|
|
157
|
-
console.log("[next-sitemap] Cleaned tsconfig (first 500 chars):", cleaned.slice(0, 500));
|
|
158
|
-
}
|
|
159
|
-
const tsconfig = JSON.parse(cleaned);
|
|
160
|
-
if (debug) {
|
|
161
|
-
console.log("[next-sitemap] Parsed tsconfig paths:", tsconfig.compilerOptions?.paths);
|
|
162
|
-
}
|
|
163
|
-
const baseUrl = tsconfig.compilerOptions?.baseUrl || ".";
|
|
164
|
-
const paths = tsconfig.compilerOptions?.paths || {};
|
|
165
|
-
for (const [key, values] of Object.entries(paths)) {
|
|
166
|
-
if (values.length > 0) {
|
|
167
|
-
const aliasKey = key.replace(/\*$/, "");
|
|
168
|
-
const aliasValue = joinPath(projectRoot, baseUrl, values[0].replace(/\*$/, ""));
|
|
169
|
-
alias[aliasKey] = aliasValue;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
} catch (error) {
|
|
174
|
-
if (debug) {
|
|
175
|
-
console.error("[next-sitemap] Error parsing tsconfig:", error);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return alias;
|
|
179
|
-
}
|
|
180
|
-
function getJiti(projectRoot, debug = false) {
|
|
181
|
-
if (jitiCache.has(projectRoot)) {
|
|
182
|
-
return jitiCache.get(projectRoot);
|
|
183
|
-
}
|
|
184
|
-
const alias = getTsconfigPaths(projectRoot, debug);
|
|
185
|
-
if (debug) {
|
|
186
|
-
console.log("[next-sitemap] Final alias config:", JSON.stringify(alias));
|
|
187
|
-
}
|
|
188
|
-
const jiti = createJiti(import.meta.url, {
|
|
189
|
-
moduleCache: false,
|
|
190
|
-
interopDefault: true,
|
|
191
|
-
jsx: true,
|
|
192
|
-
alias
|
|
193
|
-
});
|
|
194
|
-
jitiCache.set(projectRoot, jiti);
|
|
195
|
-
return jiti;
|
|
196
|
-
}
|
|
197
|
-
async function importPage(appDirectory, key, debug = false) {
|
|
198
|
-
const relativePath = key.replace("./", "");
|
|
199
|
-
const absolutePath = path.join(appDirectory, relativePath);
|
|
200
|
-
const projectRoot = process.cwd();
|
|
201
|
-
const jiti = getJiti(projectRoot, debug);
|
|
202
|
-
const module = await jiti.import(absolutePath);
|
|
203
|
-
return module.default || module;
|
|
292
|
+
const srcApp = join(process.cwd(), "src/app");
|
|
293
|
+
return existsSync(srcApp) ? srcApp : join(process.cwd(), "app");
|
|
204
294
|
}
|
|
205
295
|
function extractRoutes(pageKeys, localeSegment) {
|
|
206
296
|
const routes = [];
|
|
@@ -208,163 +298,64 @@ function extractRoutes(pageKeys, localeSegment) {
|
|
|
208
298
|
if (key.includes("[...")) continue;
|
|
209
299
|
let pathname = key.replace("./", "/").replace(/\/page\.(tsx?|jsx?)$/, "");
|
|
210
300
|
if (localeSegment) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
""
|
|
214
|
-
);
|
|
301
|
+
const escapedSegment = localeSegment.replace(/[[\]]/g, "\\$&");
|
|
302
|
+
pathname = pathname.replace(new RegExp(`^/${escapedSegment}`), "");
|
|
215
303
|
}
|
|
216
304
|
pathname = pathname.replace(/\/\([^)]+\)/g, "");
|
|
217
305
|
if (/(?:^|\/)(src|app)(?:\/|$)/.test(pathname)) continue;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
} else if (!pathname.startsWith("/")) {
|
|
306
|
+
pathname = pathname || "/";
|
|
307
|
+
if (pathname !== "/" && !pathname.startsWith("/")) {
|
|
221
308
|
pathname = "/" + pathname;
|
|
222
309
|
}
|
|
223
|
-
const dynamicSegments = pathname.match(/\[([^\]]+)\]/g)?.map((s) => s.slice(1, -1))
|
|
224
|
-
routes.push({
|
|
225
|
-
pathname,
|
|
226
|
-
dynamicSegments,
|
|
227
|
-
key
|
|
228
|
-
});
|
|
310
|
+
const dynamicSegments = pathname.match(/\[([^\]]+)\]/g)?.map((s) => s.slice(1, -1)) ?? [];
|
|
311
|
+
routes.push({ pathname, dynamicSegments, fileKey: key });
|
|
229
312
|
}
|
|
230
313
|
return routes;
|
|
231
314
|
}
|
|
232
|
-
async function getAllPaths(routes, appDirectory, debug = false) {
|
|
233
|
-
const allPaths = ["/"];
|
|
234
|
-
const seenPaths = /* @__PURE__ */ new Set(["/"]);
|
|
235
|
-
for (const route of routes) {
|
|
236
|
-
if (route.dynamicSegments.length === 0) {
|
|
237
|
-
if (route.pathname !== "/" && !seenPaths.has(route.pathname)) {
|
|
238
|
-
allPaths.push(route.pathname);
|
|
239
|
-
seenPaths.add(route.pathname);
|
|
240
|
-
}
|
|
241
|
-
} else {
|
|
242
|
-
let getParams = null;
|
|
243
|
-
try {
|
|
244
|
-
if (debug) {
|
|
245
|
-
console.log(`[next-sitemap] ${route.pathname}: importing ${route.key}`);
|
|
246
|
-
}
|
|
247
|
-
const module = await importPage(appDirectory, route.key, debug);
|
|
248
|
-
getParams = module.generateStaticParams || null;
|
|
249
|
-
} catch (error) {
|
|
250
|
-
if (debug) {
|
|
251
|
-
console.warn(`[next-sitemap] ${route.pathname}: import failed:`, error);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
if (getParams) {
|
|
255
|
-
try {
|
|
256
|
-
const params = await getParams();
|
|
257
|
-
if (debug) {
|
|
258
|
-
console.log(`[next-sitemap] ${route.pathname}: generateStaticParams returned ${params.length} params`);
|
|
259
|
-
}
|
|
260
|
-
for (const param of params) {
|
|
261
|
-
let dynamicPath = route.pathname;
|
|
262
|
-
for (const segment of route.dynamicSegments) {
|
|
263
|
-
const value = param[segment];
|
|
264
|
-
if (value === void 0) {
|
|
265
|
-
if (debug) {
|
|
266
|
-
console.warn(`[next-sitemap] ${route.pathname}: missing param "${segment}" in`, param);
|
|
267
|
-
}
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
dynamicPath = dynamicPath.replace(`[${segment}]`, value);
|
|
271
|
-
}
|
|
272
|
-
if (!seenPaths.has(dynamicPath)) {
|
|
273
|
-
allPaths.push(dynamicPath);
|
|
274
|
-
seenPaths.add(dynamicPath);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
} catch (error) {
|
|
278
|
-
console.error(`[next-sitemap] Error calling generateStaticParams for ${route.pathname}:`, error);
|
|
279
|
-
}
|
|
280
|
-
} else {
|
|
281
|
-
if (debug) {
|
|
282
|
-
console.warn(
|
|
283
|
-
`[next-sitemap] Skipping dynamic route ${route.pathname}: no generateStaticParams exported. Use additionalSitemaps for routes that fetch data at runtime.`
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
return allPaths;
|
|
290
|
-
}
|
|
291
|
-
function pathsToEntries(paths, config) {
|
|
292
|
-
const { baseUrl, locales = [], defaultLocale, exclude, priority, changeFreq } = config;
|
|
293
|
-
const filteredPaths = paths.filter((pathname) => !shouldExclude(pathname, exclude));
|
|
294
|
-
return filteredPaths.map((pathname) => {
|
|
295
|
-
const entry = {
|
|
296
|
-
url: buildUrl(baseUrl, pathname, defaultLocale, defaultLocale),
|
|
297
|
-
lastModified: /* @__PURE__ */ new Date(),
|
|
298
|
-
changeFrequency: getChangeFreq(pathname, changeFreq),
|
|
299
|
-
priority: getPriority(pathname, priority)
|
|
300
|
-
};
|
|
301
|
-
if (locales.length > 0) {
|
|
302
|
-
entry.alternates = {
|
|
303
|
-
languages: Object.fromEntries(
|
|
304
|
-
locales.map((locale) => [
|
|
305
|
-
locale,
|
|
306
|
-
buildUrl(baseUrl, pathname, locale, defaultLocale)
|
|
307
|
-
])
|
|
308
|
-
)
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
return entry;
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
315
|
function createSitemapIndexHandler(options) {
|
|
315
316
|
const { urlsPerSitemap = 5e3, locales = [], defaultLocale, additionalSitemaps, exclude, debug = false } = options;
|
|
316
317
|
const localeSegment = options.localeSegment ?? (locales.length > 0 || defaultLocale ? "[locale]" : "");
|
|
317
|
-
const appDir = resolveAppDirectory(options);
|
|
318
|
-
const pageKeys =
|
|
318
|
+
const appDir = resolveAppDirectory(options.appDirectory);
|
|
319
|
+
const pageKeys = findPageFiles(appDir);
|
|
319
320
|
const routes = extractRoutes(pageKeys, localeSegment);
|
|
320
321
|
return {
|
|
321
322
|
GET: async () => {
|
|
322
323
|
if (debug) {
|
|
323
|
-
console.log(`[next-sitemap] Found ${routes.length} routes
|
|
324
|
-
routes.forEach((r) => {
|
|
325
|
-
const isDynamic = r.dynamicSegments.length > 0;
|
|
326
|
-
const segments = isDynamic ? ` [${r.dynamicSegments.join(", ")}]` : "";
|
|
327
|
-
console.log(` ${r.pathname}${segments}${isDynamic ? " (dynamic)" : ""}`);
|
|
328
|
-
});
|
|
324
|
+
console.log(`[next-sitemap] Found ${routes.length} routes`);
|
|
329
325
|
}
|
|
330
|
-
const allPaths = await
|
|
331
|
-
const filteredPaths = allPaths.filter((
|
|
326
|
+
const allPaths = await generateAllPaths(routes, appDir, debug);
|
|
327
|
+
const filteredPaths = allPaths.filter((p) => !shouldExclude(p, exclude));
|
|
332
328
|
const sitemapCount = Math.max(1, Math.ceil(filteredPaths.length / urlsPerSitemap));
|
|
333
|
-
|
|
334
|
-
additionalSitemaps
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
headers: { "Content-Type": "application/xml" }
|
|
338
|
-
});
|
|
329
|
+
return new Response(
|
|
330
|
+
generateSitemapIndexXml(options.baseUrl, sitemapCount, { additionalSitemaps, poweredBy: options.poweredBy }),
|
|
331
|
+
{ headers: { "Content-Type": "application/xml" } }
|
|
332
|
+
);
|
|
339
333
|
}
|
|
340
334
|
};
|
|
341
335
|
}
|
|
342
336
|
function createSitemapHandler(options) {
|
|
343
337
|
const { urlsPerSitemap = 5e3, locales = [], defaultLocale, exclude, debug = false } = options;
|
|
344
338
|
const localeSegment = options.localeSegment ?? (locales.length > 0 || defaultLocale ? "[locale]" : "");
|
|
345
|
-
const appDir = resolveAppDirectory(options);
|
|
346
|
-
const pageKeys =
|
|
339
|
+
const appDir = resolveAppDirectory(options.appDirectory);
|
|
340
|
+
const pageKeys = findPageFiles(appDir);
|
|
347
341
|
const routes = extractRoutes(pageKeys, localeSegment);
|
|
348
342
|
const getFilteredPaths = async () => {
|
|
349
|
-
const allPaths = await
|
|
350
|
-
return allPaths.filter((
|
|
343
|
+
const allPaths = await generateAllPaths(routes, appDir, debug);
|
|
344
|
+
return allPaths.filter((p) => !shouldExclude(p, exclude));
|
|
351
345
|
};
|
|
352
346
|
return {
|
|
353
347
|
generateStaticParams: async () => {
|
|
354
348
|
const filteredPaths = await getFilteredPaths();
|
|
355
|
-
const
|
|
356
|
-
return Array.from({ length:
|
|
349
|
+
const count = Math.max(1, Math.ceil(filteredPaths.length / urlsPerSitemap));
|
|
350
|
+
return Array.from({ length: count }, (_, i) => ({ id: String(i) }));
|
|
357
351
|
},
|
|
358
352
|
GET: async (_request, { params }) => {
|
|
359
353
|
const { id } = await params;
|
|
360
354
|
const sitemapId = parseInt(id, 10);
|
|
361
355
|
const filteredPaths = await getFilteredPaths();
|
|
362
|
-
const
|
|
363
|
-
const end = start + urlsPerSitemap;
|
|
364
|
-
const paths = filteredPaths.slice(start, end);
|
|
356
|
+
const paths = filteredPaths.slice(sitemapId * urlsPerSitemap, (sitemapId + 1) * urlsPerSitemap);
|
|
365
357
|
const entries = pathsToEntries(paths, { ...options, exclude: void 0 });
|
|
366
|
-
|
|
367
|
-
return new Response(xml, {
|
|
358
|
+
return new Response(generateSitemapXml(entries, { poweredBy: options.poweredBy }), {
|
|
368
359
|
headers: { "Content-Type": "application/xml" }
|
|
369
360
|
});
|
|
370
361
|
}
|