generated from 0ctanium/nextjs
-
Notifications
You must be signed in to change notification settings - Fork 1
/
sitemap.ts
146 lines (129 loc) · 4.04 KB
/
sitemap.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
136
137
138
139
140
141
142
143
144
145
146
/* eslint-disable */
import { GetStaticPathsResult } from 'next';
import prettier from 'prettier';
import path from 'path';
import requireDir from 'require-dir';
import fs from 'fs';
type GenerateSitemap = (config: {
i18nConfig?: {
locales?: string[];
defaultLocale?: string;
};
basePath?: string;
domain: string;
date?: Date;
formatter?: (sitemap: string) => string;
output?: string;
}) => void;
const generateSitemap: GenerateSitemap = ({
i18nConfig = {},
basePath = '.next/server/pages',
domain,
date = new Date().toISOString(),
formatter: formatted = (sitemap) =>
prettier.format(sitemap, { parser: 'html' }),
output = 'sitemap.xml',
}) => {
const { locales, defaultLocale } = i18nConfig;
const apiFullPath = path
.resolve(`${basePath}/api`)
.replace(/([=!:$/()])/g, '\\$1');
const nextFullPath = path
.resolve(`${basePath}/next`)
.replace(/([=!:$/()])/g, '\\$1');
const apiReg = new RegExp(`^${apiFullPath}`, 'gm');
const nextReg = new RegExp(`^${nextFullPath}`, 'gm');
const dir = requireDir('../../', {
recurse: true,
duplicates: true,
filter: function (fullPath) {
const { name } = path.parse(fullPath);
return (
!nextReg.test(fullPath) && !apiReg.test(fullPath) && !/^_/g.test(name)
);
},
});
function getModules(dir: { [p: string]: any }) {
return Object.entries(dir)
.map(([pathname, module]) => {
// check if object is a module
if (module.default) {
if (!/.js/g.test(pathname)) {
// check if pathname is a dynamic route
if (/\[(.*)]/g.test(pathname)) {
// check if dynamic route exports getStaticPaths
if (module.getStaticPaths) {
const {
paths,
}: GetStaticPathsResult<{
[p: string]: string;
}> = module.getStaticPaths({
locales,
defaultLocale,
});
// loop through paths
return paths
.map((path) => {
if (typeof path === 'string') return path;
const { params } = path;
let res = pathname;
// replace [param] by actual value for each paths
Object.entries(params).forEach(([key, value]) => {
const r = new RegExp(`\\[${key}\\]`);
res = res.replace(r, value);
});
return res;
})
.flat();
}
// if route does not exports getStaticPaths => return falsy value to be filter later
return undefined;
}
return pathname;
}
return undefined;
} else {
return [
dir[`${pathname}.js`] && pathname,
...getModules(module)
.flat()
.filter(Boolean)
.map((path) => `${pathname}/${path}`),
];
}
})
.flat()
.filter(Boolean);
}
const pages = getModules(dir);
const pagesSitemap = `
${pages
.map((page) => {
const path = page
.replace('./pages/', '')
.replace('.tsx', '')
.replace(/\/index/g, '');
const routePath = path === 'index' ? '' : path;
return `
<url>
<loc>${domain}/${routePath}</loc>
<lastmod>${date}</lastmod>
</url>
`;
})
.join('')}
`;
const generatedSitemap = `
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
>
${pagesSitemap}
</urlset>
`;
const formattedSitemap = formatted(generatedSitemap);
fs.writeFileSync(`./public/${output}`, formattedSitemap, 'utf8');
};
export default generateSitemap;