boltdocs 1.3.1 → 1.3.2

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.
@@ -3,7 +3,7 @@ import {
3
3
  FileCache,
4
4
  TransformCache,
5
5
  flushCache
6
- } from "./chunk-GSYECEZY.mjs";
6
+ } from "./chunk-CYBWLFOG.mjs";
7
7
  export {
8
8
  AssetCache,
9
9
  FileCache,
@@ -34,7 +34,10 @@ function parseFrontmatter(filePath) {
34
34
  return { data, content };
35
35
  }
36
36
  function escapeHtml(str) {
37
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
37
+ return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
38
+ }
39
+ function escapeXml(str) {
40
+ return escapeHtml(str);
38
41
  }
39
42
  function fileToRoutePath(relativePath) {
40
43
  let cleanedPath = relativePath.split("/").map(stripNumberPrefix).join("/");
@@ -372,6 +375,7 @@ export {
372
375
  isDocFile,
373
376
  parseFrontmatter,
374
377
  escapeHtml,
378
+ escapeXml,
375
379
  fileToRoutePath,
376
380
  capitalize,
377
381
  FileCache,
@@ -57,7 +57,10 @@ function parseFrontmatter(filePath) {
57
57
  return { data, content };
58
58
  }
59
59
  function escapeHtml(str) {
60
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
60
+ return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
61
+ }
62
+ function escapeXml(str) {
63
+ return escapeHtml(str);
61
64
  }
62
65
  function fileToRoutePath(relativePath) {
63
66
  let cleanedPath = relativePath.split("/").map(stripNumberPrefix).join("/");
@@ -722,26 +725,24 @@ var import_url2 = require("url");
722
725
  var import_module = require("module");
723
726
 
724
727
  // src/node/ssg/meta.ts
728
+ init_utils();
725
729
  function replaceMetaTags(html, meta) {
726
- return html.replace(/<title>.*?<\/title>/, `<title>${meta.title}</title>`).replace(
730
+ const title = escapeHtml(meta.title);
731
+ const description = escapeHtml(meta.description);
732
+ return html.replace(/<title>.*?<\/title>/, `<title>${title}</title>`).replace(
727
733
  /(<meta name="description" content=")[^"]*(")/,
728
- `$1${meta.description}$2`
729
- ).replace(
730
- /(<meta property="og:title" content=")[^"]*(")/,
731
- `$1${meta.title}$2`
732
- ).replace(
734
+ `$1${description}$2`
735
+ ).replace(/(<meta property="og:title" content=")[^"]*(")/, `$1${title}$2`).replace(
733
736
  /(<meta property="og:description" content=")[^"]*(")/,
734
- `$1${meta.description}$2`
735
- ).replace(
736
- /(<meta name="twitter:title" content=")[^"]*(")/,
737
- `$1${meta.title}$2`
738
- ).replace(
737
+ `$1${description}$2`
738
+ ).replace(/(<meta name="twitter:title" content=")[^"]*(")/, `$1${title}$2`).replace(
739
739
  /(<meta name="twitter:description" content=")[^"]*(")/,
740
- `$1${meta.description}$2`
740
+ `$1${description}$2`
741
741
  );
742
742
  }
743
743
 
744
744
  // src/node/ssg/sitemap.ts
745
+ init_utils();
745
746
  function generateSitemap(routePaths, config) {
746
747
  const baseUrl = config?.siteUrl?.replace(/\/$/, "") || "https://example.com";
747
748
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -770,7 +771,7 @@ function generateSitemap(routePaths, config) {
770
771
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
771
772
  ${entries.map(
772
773
  (e) => ` <url>
773
- <loc>${baseUrl}${e.url}</loc>
774
+ <loc>${escapeXml(baseUrl)}${escapeXml(e.url)}</loc>
774
775
  <lastmod>${today}</lastmod>
775
776
  <changefreq>${e.changefreq}</changefreq>
776
777
  <priority>${e.priority}</priority>
@@ -3,13 +3,14 @@ import {
3
3
  TransformCache,
4
4
  capitalize,
5
5
  escapeHtml,
6
+ escapeXml,
6
7
  extractNumberPrefix,
7
8
  fileToRoutePath,
8
9
  isDocFile,
9
10
  normalizePath,
10
11
  parseFrontmatter,
11
12
  stripNumberPrefix
12
- } from "../chunk-GSYECEZY.mjs";
13
+ } from "../chunk-CYBWLFOG.mjs";
13
14
 
14
15
  // src/node/plugin/index.ts
15
16
  import { loadEnv } from "vite";
@@ -307,21 +308,17 @@ import { createRequire } from "module";
307
308
 
308
309
  // src/node/ssg/meta.ts
309
310
  function replaceMetaTags(html, meta) {
310
- return html.replace(/<title>.*?<\/title>/, `<title>${meta.title}</title>`).replace(
311
+ const title = escapeHtml(meta.title);
312
+ const description = escapeHtml(meta.description);
313
+ return html.replace(/<title>.*?<\/title>/, `<title>${title}</title>`).replace(
311
314
  /(<meta name="description" content=")[^"]*(")/,
312
- `$1${meta.description}$2`
313
- ).replace(
314
- /(<meta property="og:title" content=")[^"]*(")/,
315
- `$1${meta.title}$2`
316
- ).replace(
315
+ `$1${description}$2`
316
+ ).replace(/(<meta property="og:title" content=")[^"]*(")/, `$1${title}$2`).replace(
317
317
  /(<meta property="og:description" content=")[^"]*(")/,
318
- `$1${meta.description}$2`
319
- ).replace(
320
- /(<meta name="twitter:title" content=")[^"]*(")/,
321
- `$1${meta.title}$2`
322
- ).replace(
318
+ `$1${description}$2`
319
+ ).replace(/(<meta name="twitter:title" content=")[^"]*(")/, `$1${title}$2`).replace(
323
320
  /(<meta name="twitter:description" content=")[^"]*(")/,
324
- `$1${meta.description}$2`
321
+ `$1${description}$2`
325
322
  );
326
323
  }
327
324
 
@@ -354,7 +351,7 @@ function generateSitemap(routePaths, config) {
354
351
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
355
352
  ${entries.map(
356
353
  (e) => ` <url>
357
- <loc>${baseUrl}${e.url}</loc>
354
+ <loc>${escapeXml(baseUrl)}${escapeXml(e.url)}</loc>
358
355
  <lastmod>${today}</lastmod>
359
356
  <changefreq>${e.changefreq}</changefreq>
360
357
  <priority>${e.priority}</priority>
@@ -433,7 +430,7 @@ async function generateStaticPages(options) {
433
430
  console.log(
434
431
  `[boltdocs] Generated ${routes.length} static pages + sitemap.xml`
435
432
  );
436
- const { flushCache } = await import("../cache-EHR7SXRU.mjs");
433
+ const { flushCache } = await import("../cache-GQHF6BXI.mjs");
437
434
  await flushCache();
438
435
  }
439
436
 
@@ -615,7 +612,7 @@ function boltdocsPlugin(options = {}, passedConfig) {
615
612
  if (!isBuild) return;
616
613
  const outDir = viteConfig?.build?.outDir ? path4.resolve(viteConfig.root, viteConfig.build.outDir) : path4.resolve(process.cwd(), "dist");
617
614
  await generateStaticPages({ docsDir, outDir, config });
618
- const { flushCache } = await import("../cache-EHR7SXRU.mjs");
615
+ const { flushCache } = await import("../cache-GQHF6BXI.mjs");
619
616
  await flushCache();
620
617
  }
621
618
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "boltdocs",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "A lightweight documentation generator for React projects.",
5
5
  "main": "dist/node/index.js",
6
6
  "module": "dist/node/index.mjs",
@@ -1,3 +1,5 @@
1
+ import { escapeHtml } from "../utils";
2
+
1
3
  /**
2
4
  * Replaces placeholder or default meta tags in the HTML template with page-specific values.
3
5
  *
@@ -9,26 +11,23 @@ export function replaceMetaTags(
9
11
  html: string,
10
12
  meta: { title: string; description: string },
11
13
  ): string {
14
+ const title = escapeHtml(meta.title);
15
+ const description = escapeHtml(meta.description);
16
+
12
17
  return html
13
- .replace(/<title>.*?<\/title>/, `<title>${meta.title}</title>`)
18
+ .replace(/<title>.*?<\/title>/, `<title>${title}</title>`)
14
19
  .replace(
15
20
  /(<meta name="description" content=")[^"]*(")/,
16
- `$1${meta.description}$2`,
17
- )
18
- .replace(
19
- /(<meta property="og:title" content=")[^"]*(")/,
20
- `$1${meta.title}$2`,
21
+ `$1${description}$2`,
21
22
  )
23
+ .replace(/(<meta property="og:title" content=")[^"]*(")/, `$1${title}$2`)
22
24
  .replace(
23
25
  /(<meta property="og:description" content=")[^"]*(")/,
24
- `$1${meta.description}$2`,
25
- )
26
- .replace(
27
- /(<meta name="twitter:title" content=")[^"]*(")/,
28
- `$1${meta.title}$2`,
26
+ `$1${description}$2`,
29
27
  )
28
+ .replace(/(<meta name="twitter:title" content=")[^"]*(")/, `$1${title}$2`)
30
29
  .replace(
31
30
  /(<meta name="twitter:description" content=")[^"]*(")/,
32
- `$1${meta.description}$2`,
31
+ `$1${description}$2`,
33
32
  );
34
33
  }
@@ -1,4 +1,5 @@
1
1
  import { BoltdocsConfig } from "../config";
2
+ import { escapeXml } from "../utils";
2
3
 
3
4
  /**
4
5
  * Generates a standard XML sitemap for search engine crawlers.
@@ -43,7 +44,7 @@ export function generateSitemap(
43
44
  ${entries
44
45
  .map(
45
46
  (e) => ` <url>
46
- <loc>${baseUrl}${e.url}</loc>
47
+ <loc>${escapeXml(baseUrl)}${escapeXml(e.url)}</loc>
47
48
  <lastmod>${today}</lastmod>
48
49
  <changefreq>${e.changefreq}</changefreq>
49
50
  <priority>${e.priority}</priority>
package/src/node/utils.ts CHANGED
@@ -86,10 +86,21 @@ export function escapeHtml(str: string): string {
86
86
  return str
87
87
  .replace(/&/g, "&amp;")
88
88
  .replace(/"/g, "&quot;")
89
+ .replace(/'/g, "&apos;")
89
90
  .replace(/</g, "&lt;")
90
91
  .replace(/>/g, "&gt;");
91
92
  }
92
93
 
94
+ /**
95
+ * Alias for escapeHtml to be used in XML contexts (like sitemaps).
96
+ *
97
+ * @param str - The raw string to escape
98
+ * @returns The escaped string
99
+ */
100
+ export function escapeXml(str: string): string {
101
+ return escapeHtml(str);
102
+ }
103
+
93
104
  /**
94
105
  * Converts a file path relative to the `docsDir` into a URL route path.
95
106
  * Handles removing extensions, converting `index` files to directory roots,