@zubyjs/sitemap 1.0.42
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 +76 -0
- package/index.d.ts +36 -0
- package/index.js +66 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @zubyjs/sitemap
|
|
2
|
+
|
|
3
|
+
The plugin for Zuby.js that automatically generates a sitemap.xml file for your website
|
|
4
|
+
from your pages.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
First, install the `@zubyjs/sitemap` package using your favorite package manager.
|
|
9
|
+
If you aren't sure, you can use npm:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @zubyjs/sitemap
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then add the `@zubyjs/sitemap` plugin to your `zuby.config.mjs` file under the `plugins` option:
|
|
16
|
+
|
|
17
|
+
```diff lang="js" title="zuby.config.mjs"
|
|
18
|
+
import { defineConfig } from 'zuby';
|
|
19
|
+
import preact from '@zubyjs/preact';
|
|
20
|
+
+ import sitemap from '@zubyjs/sitemap';
|
|
21
|
+
|
|
22
|
+
export default defineConfig({
|
|
23
|
+
outDir: '.zuby',
|
|
24
|
+
jsx: preact(),
|
|
25
|
+
+ plugins: [
|
|
26
|
+
+ sitemap()
|
|
27
|
+
+ ]
|
|
28
|
+
^^^^^^^^
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Then add meta tag to your `pages/layout.jsx` file
|
|
33
|
+
to link the generated `sitemap.xml` file on your website:
|
|
34
|
+
|
|
35
|
+
```diff lang="jsx" title="pages/layout.jsx"
|
|
36
|
+
export default function Layout({
|
|
37
|
+
children,
|
|
38
|
+
context,
|
|
39
|
+
}) {
|
|
40
|
+
return (
|
|
41
|
+
<html>
|
|
42
|
+
<head>
|
|
43
|
+
<meta charSet="UTF-8" />
|
|
44
|
+
+ <link rel="sitemap" type="application/xml" href="/sitemap.xml" />
|
|
45
|
+
<title>{context.title}</title>
|
|
46
|
+
</head>
|
|
47
|
+
<body>{children}</body>
|
|
48
|
+
</html>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
And that's it! Now you can run `zuby build` and the sitemap.xml file will be generated.
|
|
55
|
+
|
|
56
|
+
NOTE: Always make sure that all zuby packages are in sync in your `package.json` file:
|
|
57
|
+
|
|
58
|
+
```diff lang="json"
|
|
59
|
+
{
|
|
60
|
+
"name": "my-zuby-app",
|
|
61
|
+
"version": "1.0.0",
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"zuby": "latest",
|
|
64
|
+
"@zubyjs/sitemap": "latest"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Contributing
|
|
70
|
+
|
|
71
|
+
This package is part of Zuby.js workspace and maintained by the team behind the [Zuby package](https://www.npmjs.com/package/zuby).
|
|
72
|
+
Please refer to it for more details how to contribute.
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
MIT
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ZubyPlugin } from 'zuby/types.js';
|
|
2
|
+
export interface SitemapPluginOptions {
|
|
3
|
+
/**
|
|
4
|
+
* The filter function that filters the paths that should be included in the sitemap.
|
|
5
|
+
* @example filter: (path) => path !== '/secret'
|
|
6
|
+
* @default () => true
|
|
7
|
+
*/
|
|
8
|
+
filter?: (path: string) => boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Additional custom paths that should be included in the sitemap.
|
|
11
|
+
* @example customPages: ['/custom-page', '/custom-page-2']
|
|
12
|
+
* @default []
|
|
13
|
+
*/
|
|
14
|
+
customPages?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* The maximum number of entries per sitemap file.
|
|
17
|
+
* @example entryLimit: 10000
|
|
18
|
+
* @default 45000
|
|
19
|
+
*/
|
|
20
|
+
entryLimit?: number;
|
|
21
|
+
/**
|
|
22
|
+
* The name of the sitemap file without extension.
|
|
23
|
+
* @example filename: 'my-sitemap'
|
|
24
|
+
* @default 'sitemap'
|
|
25
|
+
*/
|
|
26
|
+
filename?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Zuby.js plugin that generates sitemap.xml
|
|
30
|
+
* from pre-rendered paths.
|
|
31
|
+
* @param options
|
|
32
|
+
* @returns ZubyPlugin
|
|
33
|
+
*/
|
|
34
|
+
declare const _default: ({ filter, customPages, entryLimit, filename, }?: SitemapPluginOptions) => ZubyPlugin;
|
|
35
|
+
export default _default;
|
|
36
|
+
export declare function splitToParts(array: string[], parts: number): string[][];
|
package/index.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import { writeFile } from 'fs/promises';
|
|
3
|
+
/**
|
|
4
|
+
* Zuby.js plugin that generates sitemap.xml
|
|
5
|
+
* from pre-rendered paths.
|
|
6
|
+
* @param options
|
|
7
|
+
* @returns ZubyPlugin
|
|
8
|
+
*/
|
|
9
|
+
export default ({ filter = () => true, customPages = [], entryLimit = 45000, filename = 'sitemap', } = {}) => ({
|
|
10
|
+
name: 'zuby-sitemap-plugin',
|
|
11
|
+
description: 'generating sitemap.xml...',
|
|
12
|
+
buildStep: true,
|
|
13
|
+
hooks: {
|
|
14
|
+
'zuby:build:done': async ({ config, logger }) => {
|
|
15
|
+
const { site, outDir, i18n, prerenderPaths } = config;
|
|
16
|
+
if (!site) {
|
|
17
|
+
logger?.warn(`WARNING: The "site" property is not defined in zuby.config.mjs. Skipping sitemap generation.`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
logger.info('Generating sitemap from pre-rendered paths...');
|
|
21
|
+
const removeLocale = (path) => {
|
|
22
|
+
for (const locale of i18n?.locales || []) {
|
|
23
|
+
if (path.startsWith(`/${locale}/`))
|
|
24
|
+
return path.replace(`/${locale}/`, '/');
|
|
25
|
+
if (path === `/${locale}`)
|
|
26
|
+
return '/';
|
|
27
|
+
}
|
|
28
|
+
return path;
|
|
29
|
+
};
|
|
30
|
+
const normalizePath = (path) => {
|
|
31
|
+
return path.replace(/(.+)\/$/, '').replace(/\/\/+/g, '/');
|
|
32
|
+
};
|
|
33
|
+
const paths = [...customPages, ...prerenderPaths.filter(filter)].map(normalizePath);
|
|
34
|
+
const entries = paths.map(path => {
|
|
35
|
+
const localizedPaths = i18n
|
|
36
|
+
? paths.filter(filteredPath => {
|
|
37
|
+
return removeLocale(path) === removeLocale(filteredPath);
|
|
38
|
+
})
|
|
39
|
+
: [];
|
|
40
|
+
const alternateLinks = localizedPaths.map(path => {
|
|
41
|
+
const locale = i18n.locales.find(locale => path.startsWith(`/${locale}`)) || i18n.defaultLocale;
|
|
42
|
+
return `<xhtml:link rel="alternate" hreflang="${locale}" href="${new URL(path, config.site).href}" />`;
|
|
43
|
+
});
|
|
44
|
+
return `<url><loc>${new URL(path, config.site).href}</loc>${alternateLinks.join('')}</url>`;
|
|
45
|
+
});
|
|
46
|
+
const parts = Math.ceil(entries.length / entryLimit);
|
|
47
|
+
const entriesParts = splitToParts(entries, parts);
|
|
48
|
+
const subSitemapPromises = entriesParts.map((entries, index) => {
|
|
49
|
+
return writeFile(normalizePath(resolve(outDir, 'client', `${filename}-${index}.xml`)), `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${entries.join('\r\n')}</urlset>`);
|
|
50
|
+
});
|
|
51
|
+
await Promise.all(subSitemapPromises);
|
|
52
|
+
const sitemapIndexEntries = entriesParts.map((_, index) => {
|
|
53
|
+
return `<sitemap><loc>${new URL(`${filename}-${index}.xml`, site).href}</loc></sitemap>`;
|
|
54
|
+
});
|
|
55
|
+
await writeFile(normalizePath(resolve(outDir, 'client', `${filename}.xml`)), `<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${sitemapIndexEntries.join('\r\n')}</sitemapindex>`);
|
|
56
|
+
logger.info(`Generated ${filename}.xml`);
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
export function splitToParts(array, parts) {
|
|
61
|
+
const result = [];
|
|
62
|
+
for (let i = parts; i > 0; i--) {
|
|
63
|
+
result.push(array.splice(0, Math.ceil(array.length / i)));
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zubyjs/sitemap",
|
|
3
|
+
"version": "1.0.42",
|
|
4
|
+
"description": "Zuby.js sitemap plugin",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"release": "cd ./dist && npm publish --access public && cd ..",
|
|
9
|
+
"bump-version": "npm version patch",
|
|
10
|
+
"build": "rm -rf dist/ stage/ && mkdir dist && tsc && cp -rf package.json README.md stage/sitemap/src/* dist/ && rm -rf stage/",
|
|
11
|
+
"push-build": "npm run build && cd dist && yalc push --force && cd ..",
|
|
12
|
+
"test": "exit 0"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"directory": "dist",
|
|
16
|
+
"linkDirectory": true
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"zuby": "^1.0.0"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://gitlab.com/futrou/zuby.js/-/issues",
|
|
23
|
+
"email": "zuby@futrou.com"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://gitlab.com/futrou/zuby.js.git"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://zuby.futrou.com",
|
|
31
|
+
"keywords": [
|
|
32
|
+
"zuby-plugin",
|
|
33
|
+
"zuby",
|
|
34
|
+
"sitemap",
|
|
35
|
+
"seo"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=16"
|
|
39
|
+
}
|
|
40
|
+
}
|