vite-plugin-sitemap-ts 1.0.0 → 1.1.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 CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  A Vite plugin to generate `sitemap.xml`. Works in development mode by proxying middleware to `/sitemap.xml`.
4
4
 
5
- > [!IMPORTANT]
6
- > This plugin is actively being devloped. DO NOT USE IN PRODUCTION!
5
+ > [!WARNING]
6
+ > **DO NOT USE IN PRODUCTION!** This plugin is actively being devloped.
7
7
 
8
8
  ## Installation
9
9
 
@@ -23,16 +23,20 @@ import { sitemap } from 'vite-plugin-sitemap-ts'
23
23
 
24
24
  export default {
25
25
  plugins: [
26
- sitemap(),
26
+ sitemap({
27
+ hostname: 'https://example.com',
28
+ }),
27
29
  ],
28
30
  }
29
31
  ```
30
32
 
31
33
  ## Options
32
34
 
33
- All options are optional.
35
+ The `hostname` option is required. All other options are optional.
34
36
 
35
- | Option | Type | Default | Description |
36
- |---------|------------------------------------|---------|------------------------------------------------------------------------------|
37
- | enabled | *boolean* | `true` | Toggle the plugin on or off |
37
+ | Option | Type | Default | Description |
38
+ |----------|------------|---------|----------------------------------------------------------------------|
39
+ | hostname | *string* | - | The hostname of the site, used to build the full URLs in the sitemap |
40
+ | enabled | *boolean* | `true` | Toggle the plugin on or off |
41
+ | routes | *string[]* | `['/']` | An array of routes to include in the sitemap |
38
42
 
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -24,10 +34,69 @@ __export(index_exports, {
24
34
  });
25
35
  module.exports = __toCommonJS(index_exports);
26
36
 
37
+ // src/plugin.ts
38
+ var import_node_fs = __toESM(require("fs"), 1);
39
+ var import_node_path = __toESM(require("path"), 1);
40
+
27
41
  // src/utils.ts
28
- var SITEMAP_CONTENT = `<?xml version="1.0" encoding="UTF-8"?>
29
- <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
42
+ var SPACER = " ";
43
+ var DSPACER = SPACER + SPACER;
44
+ var xmlHeader = `<?xml version="1.0" encoding="UTF-8"?>`;
45
+ var xmlSchema = (content) => {
46
+ return `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
47
+ ${content}
30
48
  </urlset>`;
49
+ };
50
+ var escapeXml = (value) => {
51
+ return String(value).replace(/[&<>"']/g, (ch) => {
52
+ switch (ch) {
53
+ case "&":
54
+ return "&amp;";
55
+ case "<":
56
+ return "&lt;";
57
+ case ">":
58
+ return "&gt;";
59
+ case '"':
60
+ return "&quot;";
61
+ case "'":
62
+ return "&apos;";
63
+ default:
64
+ return ch;
65
+ }
66
+ });
67
+ };
68
+ var generateSitemap = (entries) => {
69
+ const urls = entries.map((entry) => {
70
+ let sitemapEntry = `${DSPACER}<loc>${escapeXml(entry.loc)}</loc>`;
71
+ if (entry.lastmod) {
72
+ sitemapEntry += `
73
+ ${DSPACER}<lastmod>${escapeXml(entry.lastmod)}</lastmod>`;
74
+ }
75
+ if (entry.changefreq) {
76
+ sitemapEntry += `
77
+ ${DSPACER}<changefreq>${escapeXml(entry.changefreq)}</changefreq>`;
78
+ }
79
+ if (entry.priority !== void 0) {
80
+ sitemapEntry += `
81
+ ${DSPACER}<priority>${escapeXml(entry.priority)}</priority>`;
82
+ }
83
+ return `${SPACER}<url>
84
+ ${sitemapEntry}
85
+ ${SPACER}</url>`;
86
+ }).join("\n");
87
+ return `${xmlHeader}
88
+ ${xmlSchema(urls)}`;
89
+ };
90
+ var buildSitemapEntries = (options) => {
91
+ const host = options.hostname.replace(/\/$/, "");
92
+ const lastmod = (/* @__PURE__ */ new Date()).toISOString();
93
+ return options.routes.map((route) => {
94
+ return {
95
+ loc: `${host}/${route.replace(/^\/+/, "")}`,
96
+ lastmod
97
+ };
98
+ });
99
+ };
31
100
  var logColor = (color, text, bold = false) => {
32
101
  const colorCode = {
33
102
  red: bold ? "\x1B[1;31m" : "\x1B[31m",
@@ -45,11 +114,15 @@ var LOGGER_FAILURE = logColor("red", "\u2717", true);
45
114
  var BASE_PATH = "/";
46
115
  var FILE_NAME = "sitemap.xml";
47
116
  var SITEMAP_PATH = `${BASE_PATH}${FILE_NAME}`;
48
- function sitemap(options = {}) {
117
+ function sitemap(options) {
49
118
  let config;
50
119
  let success = false;
51
- const sitemapContent = SITEMAP_CONTENT;
52
120
  const enabled = options.enabled ?? true;
121
+ const host = options.hostname ?? void 0;
122
+ const routes = options.routes ?? ["/"];
123
+ if (!host) {
124
+ throw new Error("Sitemap hostname is not set and required to build the sitemap.");
125
+ }
53
126
  return {
54
127
  name: "vite-plugin-sitemap-ts",
55
128
  apply: () => enabled,
@@ -58,27 +131,30 @@ function sitemap(options = {}) {
58
131
  },
59
132
  configureServer(server) {
60
133
  server.middlewares.use(SITEMAP_PATH, (_req, res) => {
134
+ const entries = buildSitemapEntries({ hostname: host, routes });
135
+ const content = generateSitemap(entries);
61
136
  res.setHeader("Content-Type", "text/xml; charset=utf-8");
62
- res.end(sitemapContent);
137
+ res.end(content);
63
138
  });
64
139
  config.logger.info(
65
140
  `${LOGGER_CLEAR}${LOGGER_SUCCESS} ${LOGGER_PREFIX} Exposed new route: ${logColor("green", SITEMAP_PATH)}`
66
141
  );
67
142
  },
68
- generateBundle() {
69
- if (this.environment?.name && this.environment.name !== "client") {
70
- return;
143
+ closeBundle() {
144
+ if (this.environment) {
145
+ if (this.environment.name !== "client" || this.environment.mode === "dev") {
146
+ return;
147
+ }
71
148
  }
72
- config.logger.info(
73
- `
74
- - ${LOGGER_CLEAR}${LOGGER_PREFIX} Writing sitemap.xml at ${config.build.outDir}${SITEMAP_PATH}`
75
- );
149
+ const outDir = config.build.outDir.replace("server", "client");
150
+ config.logger.info(`
151
+ - ${LOGGER_CLEAR}${LOGGER_PREFIX} Writing sitemap.xml at ${outDir}${SITEMAP_PATH}`);
76
152
  try {
77
- this.emitFile({
78
- type: "asset",
79
- fileName: FILE_NAME,
80
- source: sitemapContent
81
- });
153
+ const entries = buildSitemapEntries({ hostname: host, routes });
154
+ const content = generateSitemap(entries);
155
+ const outDirPath = import_node_path.default.resolve(config.root, outDir);
156
+ const filePath = import_node_path.default.join(outDirPath, FILE_NAME);
157
+ import_node_fs.default.writeFileSync(filePath, content, "utf-8");
82
158
  success = true;
83
159
  } catch (_err) {
84
160
  success = false;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,12 @@
1
1
  import { Plugin } from 'vite';
2
2
 
3
+ type ChangeFreq = 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
4
+ type SitemapEntry = {
5
+ loc: string;
6
+ lastmod?: string;
7
+ priority?: number;
8
+ changefreq?: ChangeFreq;
9
+ };
3
10
  type Options = {
4
11
  /**
5
12
  * Toggle the plugin on or off. Useful if you want to disable the plugin, e.g. in development mode.
@@ -7,8 +14,20 @@ type Options = {
7
14
  * **Default: `true`**
8
15
  */
9
16
  enabled?: boolean;
17
+ /**
18
+ * The hostname of the site, used to build the full URLs in the sitemap.
19
+ *
20
+ * **Example: `'https://example.com'`**
21
+ */
22
+ hostname: string;
23
+ /**
24
+ * An array of routes to include in the sitemap.
25
+ *
26
+ * **Default: `['/']`**
27
+ */
28
+ routes?: string[];
10
29
  };
11
30
 
12
- declare function sitemap(options?: Options): Plugin;
31
+ declare function sitemap(options: Options): Plugin;
13
32
 
14
- export { type Options, sitemap };
33
+ export { type ChangeFreq, type Options, type SitemapEntry, sitemap };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  import { Plugin } from 'vite';
2
2
 
3
+ type ChangeFreq = 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
4
+ type SitemapEntry = {
5
+ loc: string;
6
+ lastmod?: string;
7
+ priority?: number;
8
+ changefreq?: ChangeFreq;
9
+ };
3
10
  type Options = {
4
11
  /**
5
12
  * Toggle the plugin on or off. Useful if you want to disable the plugin, e.g. in development mode.
@@ -7,8 +14,20 @@ type Options = {
7
14
  * **Default: `true`**
8
15
  */
9
16
  enabled?: boolean;
17
+ /**
18
+ * The hostname of the site, used to build the full URLs in the sitemap.
19
+ *
20
+ * **Example: `'https://example.com'`**
21
+ */
22
+ hostname: string;
23
+ /**
24
+ * An array of routes to include in the sitemap.
25
+ *
26
+ * **Default: `['/']`**
27
+ */
28
+ routes?: string[];
10
29
  };
11
30
 
12
- declare function sitemap(options?: Options): Plugin;
31
+ declare function sitemap(options: Options): Plugin;
13
32
 
14
- export { type Options, sitemap };
33
+ export { type ChangeFreq, type Options, type SitemapEntry, sitemap };
package/dist/index.js CHANGED
@@ -1,7 +1,66 @@
1
+ // src/plugin.ts
2
+ import fs from "fs";
3
+ import path from "path";
4
+
1
5
  // src/utils.ts
2
- var SITEMAP_CONTENT = `<?xml version="1.0" encoding="UTF-8"?>
3
- <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
6
+ var SPACER = " ";
7
+ var DSPACER = SPACER + SPACER;
8
+ var xmlHeader = `<?xml version="1.0" encoding="UTF-8"?>`;
9
+ var xmlSchema = (content) => {
10
+ return `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
11
+ ${content}
4
12
  </urlset>`;
13
+ };
14
+ var escapeXml = (value) => {
15
+ return String(value).replace(/[&<>"']/g, (ch) => {
16
+ switch (ch) {
17
+ case "&":
18
+ return "&amp;";
19
+ case "<":
20
+ return "&lt;";
21
+ case ">":
22
+ return "&gt;";
23
+ case '"':
24
+ return "&quot;";
25
+ case "'":
26
+ return "&apos;";
27
+ default:
28
+ return ch;
29
+ }
30
+ });
31
+ };
32
+ var generateSitemap = (entries) => {
33
+ const urls = entries.map((entry) => {
34
+ let sitemapEntry = `${DSPACER}<loc>${escapeXml(entry.loc)}</loc>`;
35
+ if (entry.lastmod) {
36
+ sitemapEntry += `
37
+ ${DSPACER}<lastmod>${escapeXml(entry.lastmod)}</lastmod>`;
38
+ }
39
+ if (entry.changefreq) {
40
+ sitemapEntry += `
41
+ ${DSPACER}<changefreq>${escapeXml(entry.changefreq)}</changefreq>`;
42
+ }
43
+ if (entry.priority !== void 0) {
44
+ sitemapEntry += `
45
+ ${DSPACER}<priority>${escapeXml(entry.priority)}</priority>`;
46
+ }
47
+ return `${SPACER}<url>
48
+ ${sitemapEntry}
49
+ ${SPACER}</url>`;
50
+ }).join("\n");
51
+ return `${xmlHeader}
52
+ ${xmlSchema(urls)}`;
53
+ };
54
+ var buildSitemapEntries = (options) => {
55
+ const host = options.hostname.replace(/\/$/, "");
56
+ const lastmod = (/* @__PURE__ */ new Date()).toISOString();
57
+ return options.routes.map((route) => {
58
+ return {
59
+ loc: `${host}/${route.replace(/^\/+/, "")}`,
60
+ lastmod
61
+ };
62
+ });
63
+ };
5
64
  var logColor = (color, text, bold = false) => {
6
65
  const colorCode = {
7
66
  red: bold ? "\x1B[1;31m" : "\x1B[31m",
@@ -19,11 +78,15 @@ var LOGGER_FAILURE = logColor("red", "\u2717", true);
19
78
  var BASE_PATH = "/";
20
79
  var FILE_NAME = "sitemap.xml";
21
80
  var SITEMAP_PATH = `${BASE_PATH}${FILE_NAME}`;
22
- function sitemap(options = {}) {
81
+ function sitemap(options) {
23
82
  let config;
24
83
  let success = false;
25
- const sitemapContent = SITEMAP_CONTENT;
26
84
  const enabled = options.enabled ?? true;
85
+ const host = options.hostname ?? void 0;
86
+ const routes = options.routes ?? ["/"];
87
+ if (!host) {
88
+ throw new Error("Sitemap hostname is not set and required to build the sitemap.");
89
+ }
27
90
  return {
28
91
  name: "vite-plugin-sitemap-ts",
29
92
  apply: () => enabled,
@@ -32,27 +95,30 @@ function sitemap(options = {}) {
32
95
  },
33
96
  configureServer(server) {
34
97
  server.middlewares.use(SITEMAP_PATH, (_req, res) => {
98
+ const entries = buildSitemapEntries({ hostname: host, routes });
99
+ const content = generateSitemap(entries);
35
100
  res.setHeader("Content-Type", "text/xml; charset=utf-8");
36
- res.end(sitemapContent);
101
+ res.end(content);
37
102
  });
38
103
  config.logger.info(
39
104
  `${LOGGER_CLEAR}${LOGGER_SUCCESS} ${LOGGER_PREFIX} Exposed new route: ${logColor("green", SITEMAP_PATH)}`
40
105
  );
41
106
  },
42
- generateBundle() {
43
- if (this.environment?.name && this.environment.name !== "client") {
44
- return;
107
+ closeBundle() {
108
+ if (this.environment) {
109
+ if (this.environment.name !== "client" || this.environment.mode === "dev") {
110
+ return;
111
+ }
45
112
  }
46
- config.logger.info(
47
- `
48
- - ${LOGGER_CLEAR}${LOGGER_PREFIX} Writing sitemap.xml at ${config.build.outDir}${SITEMAP_PATH}`
49
- );
113
+ const outDir = config.build.outDir.replace("server", "client");
114
+ config.logger.info(`
115
+ - ${LOGGER_CLEAR}${LOGGER_PREFIX} Writing sitemap.xml at ${outDir}${SITEMAP_PATH}`);
50
116
  try {
51
- this.emitFile({
52
- type: "asset",
53
- fileName: FILE_NAME,
54
- source: sitemapContent
55
- });
117
+ const entries = buildSitemapEntries({ hostname: host, routes });
118
+ const content = generateSitemap(entries);
119
+ const outDirPath = path.resolve(config.root, outDir);
120
+ const filePath = path.join(outDirPath, FILE_NAME);
121
+ fs.writeFileSync(filePath, content, "utf-8");
56
122
  success = true;
57
123
  } catch (_err) {
58
124
  success = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-sitemap-ts",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Vite plugin to generate sitemap.xml. Works in dev mode.",
5
5
  "author": "Cornelius Weidmann <cornelius@kyco.io> (https://kyco.io)",
6
6
  "license": "MIT",
@@ -63,7 +63,7 @@
63
63
  "vite": ">=2"
64
64
  },
65
65
  "devDependencies": {
66
- "@biomejs/biome": "^2.4.6",
66
+ "@biomejs/biome": "^2.4.7",
67
67
  "@semantic-release/changelog": "^6.0.3",
68
68
  "@semantic-release/git": "^10.0.1",
69
69
  "@semantic-release/github": "^12.0.6",