@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.
Files changed (4) hide show
  1. package/README.md +76 -0
  2. package/index.d.ts +36 -0
  3. package/index.js +66 -0
  4. 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
+ }