mdsvr 2.4.0 → 2.5.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.
Files changed (93) hide show
  1. package/dist/directory.d.ts +11 -0
  2. package/dist/directory.d.ts.map +1 -1
  3. package/dist/directory.js +31 -115
  4. package/dist/directory.js.map +1 -1
  5. package/dist/generators/feed.d.ts.map +1 -1
  6. package/dist/generators/feed.js +9 -2
  7. package/dist/generators/feed.js.map +1 -1
  8. package/dist/generators/robots.d.ts +11 -0
  9. package/dist/generators/robots.d.ts.map +1 -0
  10. package/dist/generators/robots.js +32 -0
  11. package/dist/generators/robots.js.map +1 -0
  12. package/dist/generators/search-index.d.ts.map +1 -1
  13. package/dist/generators/search-index.js +6 -5
  14. package/dist/generators/search-index.js.map +1 -1
  15. package/dist/generators/sitemap.d.ts +17 -1
  16. package/dist/generators/sitemap.d.ts.map +1 -1
  17. package/dist/generators/sitemap.js +119 -59
  18. package/dist/generators/sitemap.js.map +1 -1
  19. package/dist/generators/static-export.d.ts.map +1 -1
  20. package/dist/generators/static-export.js +66 -11
  21. package/dist/generators/static-export.js.map +1 -1
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/link-transform.d.ts +37 -5
  26. package/dist/link-transform.d.ts.map +1 -1
  27. package/dist/link-transform.js +120 -13
  28. package/dist/link-transform.js.map +1 -1
  29. package/dist/render-page.d.ts +1 -2
  30. package/dist/render-page.d.ts.map +1 -1
  31. package/dist/render-page.js +56 -40
  32. package/dist/render-page.js.map +1 -1
  33. package/dist/renderer/markdown.d.ts +0 -16
  34. package/dist/renderer/markdown.d.ts.map +1 -1
  35. package/dist/renderer/markdown.js +6 -63
  36. package/dist/renderer/markdown.js.map +1 -1
  37. package/dist/router.d.ts.map +1 -1
  38. package/dist/router.js +19 -1
  39. package/dist/router.js.map +1 -1
  40. package/dist/seo/extract.d.ts +26 -0
  41. package/dist/seo/extract.d.ts.map +1 -0
  42. package/dist/seo/extract.js +159 -0
  43. package/dist/seo/extract.js.map +1 -0
  44. package/dist/seo/index.d.ts +5 -0
  45. package/dist/seo/index.d.ts.map +1 -0
  46. package/dist/seo/index.js +5 -0
  47. package/dist/seo/index.js.map +1 -0
  48. package/dist/seo/jsonld.d.ts +15 -0
  49. package/dist/seo/jsonld.d.ts.map +1 -0
  50. package/dist/seo/jsonld.js +93 -0
  51. package/dist/seo/jsonld.js.map +1 -0
  52. package/dist/seo/metadata.d.ts +60 -0
  53. package/dist/seo/metadata.d.ts.map +1 -0
  54. package/dist/seo/metadata.js +144 -0
  55. package/dist/seo/metadata.js.map +1 -0
  56. package/dist/seo/url.d.ts +27 -0
  57. package/dist/seo/url.d.ts.map +1 -0
  58. package/dist/seo/url.js +76 -0
  59. package/dist/seo/url.js.map +1 -0
  60. package/dist/settings/defaults.d.ts.map +1 -1
  61. package/dist/settings/defaults.js +0 -2
  62. package/dist/settings/defaults.js.map +1 -1
  63. package/dist/settings/index.d.ts +1 -1
  64. package/dist/settings/index.d.ts.map +1 -1
  65. package/dist/settings/index.js +15 -0
  66. package/dist/settings/index.js.map +1 -1
  67. package/dist/settings/schema.d.ts +317 -5
  68. package/dist/settings/schema.d.ts.map +1 -1
  69. package/dist/settings/schema.js +45 -1
  70. package/dist/settings/schema.js.map +1 -1
  71. package/dist/template/analytics.d.ts +18 -0
  72. package/dist/template/analytics.d.ts.map +1 -0
  73. package/dist/template/analytics.js +83 -0
  74. package/dist/template/analytics.js.map +1 -0
  75. package/dist/template/index.d.ts +5 -0
  76. package/dist/template/index.d.ts.map +1 -1
  77. package/dist/template/index.js +59 -59
  78. package/dist/template/index.js.map +1 -1
  79. package/dist/template/search.d.ts.map +1 -1
  80. package/dist/template/search.js +9 -2
  81. package/dist/template/search.js.map +1 -1
  82. package/dist/template/seo.d.ts +7 -10
  83. package/dist/template/seo.d.ts.map +1 -1
  84. package/dist/template/seo.js +57 -33
  85. package/dist/template/seo.js.map +1 -1
  86. package/dist/template/sidebar.d.ts.map +1 -1
  87. package/dist/template/sidebar.js +11 -8
  88. package/dist/template/sidebar.js.map +1 -1
  89. package/dist/validator/index.d.ts +1 -1
  90. package/dist/validator/index.d.ts.map +1 -1
  91. package/dist/validator/index.js +21 -0
  92. package/dist/validator/index.js.map +1 -1
  93. package/package.json +1 -1
@@ -1,6 +1,17 @@
1
1
  import type { Dirent } from "node:fs";
2
+ /**
3
+ * Render a directory listing as a body fragment for auto-index pages.
4
+ * The surrounding document (head, navigation, styles) comes from the page
5
+ * template — this returns only `<h1>` + the listing table.
6
+ *
7
+ * File links use the canonical clean-URL form: `.md`/`.mdx` entries point to
8
+ * the trailing-slash doc route; index files (README/index) are hidden because
9
+ * they are the page itself.
10
+ */
2
11
  export declare function renderDirectory(params: {
3
12
  urlPath: string;
4
13
  entries: Dirent[];
14
+ /** Heading text; defaults to a humanized form of the last URL segment. */
15
+ title?: string;
5
16
  }): string;
6
17
  //# sourceMappingURL=directory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,GAAG,MAAM,CA+IT"}
1
+ {"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CA+DT"}
package/dist/directory.js CHANGED
@@ -1,21 +1,39 @@
1
+ /**
2
+ * Render a directory listing as a body fragment for auto-index pages.
3
+ * The surrounding document (head, navigation, styles) comes from the page
4
+ * template — this returns only `<h1>` + the listing table.
5
+ *
6
+ * File links use the canonical clean-URL form: `.md`/`.mdx` entries point to
7
+ * the trailing-slash doc route; index files (README/index) are hidden because
8
+ * they are the page itself.
9
+ */
1
10
  export function renderDirectory(params) {
2
11
  const { urlPath, entries } = params;
12
+ const lastSegment = urlPath.replace(/\/+$/, "").split("/").pop() || "";
13
+ const title = params.title ??
14
+ (lastSegment
15
+ ? decodeURIComponent(lastSegment).replace(/[-_]/g, " ")
16
+ : "Index");
3
17
  // Sort: folders first, then files (alphabetically)
4
- const sorted = [...entries].sort((a, b) => {
18
+ const sorted = [...entries]
19
+ .filter((entry) => !isIndexEntry(entry.name))
20
+ .sort((a, b) => {
5
21
  if (a.isDirectory() && !b.isDirectory())
6
22
  return -1;
7
23
  if (!a.isDirectory() && b.isDirectory())
8
24
  return 1;
9
25
  return a.name.localeCompare(b.name);
10
26
  });
27
+ const base = urlPath.replace(/\/+$/, "") + "/";
11
28
  const rows = sorted
12
29
  .map((entry) => {
13
30
  const name = entry.name;
14
31
  const isDir = entry.isDirectory();
15
- const icon = isDir ? "📁" : name.endsWith(".md") ? "📄" : "📃";
16
- const href = (urlPath ? urlPath.replace(/\/+$/, "") + "/" : "") +
17
- encodeURIComponent(name) +
18
- (isDir ? "/" : "");
32
+ const isDoc = /\.(md|mdx)$/i.test(name);
33
+ const icon = isDir ? "📁" : isDoc ? "📄" : "📃";
34
+ const href = isDir || isDoc
35
+ ? `${base}${encodeURIComponent(name.replace(/\.(md|mdx)$/i, ""))}/`
36
+ : `${base}${encodeURIComponent(name)}`;
19
37
  const size = !isDir && entry.isFile()
20
38
  ? formatSize(entry.size || 0)
21
39
  : "-";
@@ -25,104 +43,15 @@ export function renderDirectory(params) {
25
43
  </tr>`;
26
44
  })
27
45
  .join("\n");
28
- const breadcrumb = generateBreadcrumb(urlPath);
29
- // Theme script for dark mode support
30
- const themeScript = `
31
- <script>
32
- (function() {
33
- var theme = localStorage.getItem('theme') || 'system';
34
- if (theme === 'system') {
35
- theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
36
- }
37
- document.documentElement.setAttribute('data-theme', theme);
38
- })();
39
- </script>`;
40
- return `<!DOCTYPE html>
41
- <html lang="en" data-theme="light">
42
- <head>
43
- <meta charset="UTF-8">
44
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
45
- <title>Index of ${escapeHtml(urlPath)}</title>
46
- ${themeScript}
47
- <style>
48
- :root {
49
- --bg: #f6f8fa;
50
- --bg-secondary: #ffffff;
51
- --text: #24292f;
52
- --text-muted: #656d76;
53
- --border: #d0d7de;
54
- --accent: #0969da;
55
- --header-bg: #0d1117;
56
- --header-text: #f0f6fc;
57
- --header-border: #30363d;
58
- }
59
- :root[data-theme="dark"] {
60
- --bg: #0d1117;
61
- --bg-secondary: #161b22;
62
- --text: #e6edf3;
63
- --text-muted: #8d96a0;
64
- --border: #30363d;
65
- --accent: #58a6ff;
66
- --header-bg: #161b22;
67
- --header-text: #e6edf3;
68
- --header-border: #30363d;
69
- }
70
- * { box-sizing: border-box; }
71
- body {
72
- margin: 0;
73
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
74
- font-size: 16px;
75
- line-height: 1.6;
76
- color: var(--text);
77
- background: var(--bg);
78
- }
79
- .header {
80
- background: var(--header-bg);
81
- padding: 16px 24px;
82
- border-bottom: 1px solid var(--header-border);
83
- }
84
- .header-logo {
85
- color: var(--header-text);
86
- font-weight: 600;
87
- font-size: 14px;
88
- text-decoration: none;
89
- }
90
- .container {
91
- max-width: 860px;
92
- margin: 32px auto;
93
- padding: 32px;
94
- background: var(--bg-secondary);
95
- border: 1px solid var(--border);
96
- border-radius: 6px;
97
- }
98
- h1 { font-size: 20px; font-weight: 600; margin: 0 0 16px; color: var(--text); }
99
- .breadcrumb { font-size: 14px; color: var(--text-muted); margin-bottom: 20px; }
100
- .breadcrumb a { color: var(--accent); text-decoration: none; }
101
- .breadcrumb a:hover { text-decoration: underline; }
102
- table { width: 100%; border-collapse: collapse; }
103
- th, td { padding: 8px 12px; text-align: left; border-bottom: 1px solid var(--border); }
104
- th { font-weight: 600; color: var(--text-muted); font-size: 14px; }
105
- td { font-size: 14px; }
106
- td a { color: var(--accent); text-decoration: none; }
107
- td a:hover { text-decoration: underline; }
108
- .size { color: var(--text-muted); text-align: right; width: 100px; }
109
- .empty { color: var(--text-muted); font-style: italic; padding: 24px 0; }
110
- @media (max-width: 900px) {
111
- .container { margin: 16px; padding: 20px; }
112
- .header { padding: 12px 16px; }
113
- }
114
- @media (max-width: 480px) {
115
- .container { margin: 8px; padding: 16px; }
116
- }
117
- </style>
118
- </head>
119
- <body>
46
+ const hasParent = urlPath !== "" && urlPath !== "/";
47
+ return `<h1>${escapeHtml(title)}</h1>
48
+ <nav class="dir-listing" aria-label="Directory listing">
120
49
  <table>
121
50
  <thead>
122
51
  <tr><th>Name</th><th class="size">Size</th></tr>
123
52
  </thead>
124
53
  <tbody>
125
- ${urlPath
54
+ ${hasParent
126
55
  ? ` <tr>
127
56
  <td>📁 <a href="../">../</a></td>
128
57
  <td class="size">-</td>
@@ -131,24 +60,11 @@ ${urlPath
131
60
  ${rows || ' <tr><td colspan="2" class="empty">Empty directory</td></tr>'}
132
61
  </tbody>
133
62
  </table>
134
- </body>
135
- </html>`;
63
+ </nav>`;
136
64
  }
137
- function generateBreadcrumb(urlPath) {
138
- if (!urlPath || urlPath === "/") {
139
- return "<strong>home</strong>";
140
- }
141
- const parts = urlPath.split("/").filter(Boolean);
142
- let accum = "";
143
- const links = parts.map((part, i) => {
144
- accum += "/" + part;
145
- const isLast = i === parts.length - 1;
146
- if (isLast) {
147
- return `<strong>${escapeHtml(part)}</strong>`;
148
- }
149
- return `<a href="${accum}/">${escapeHtml(part)}</a>`;
150
- });
151
- return '<a href="/">home</a> / ' + links.join(" / ");
65
+ /** Index files render as the directory page itself — hide them in listings. */
66
+ function isIndexEntry(name) {
67
+ return /^(readme|index)\.(md|mdx|html?)$/i.test(name);
152
68
  }
153
69
  function formatSize(bytes) {
154
70
  if (bytes === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"directory.js","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"directory.js","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../../src/generators/feed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAiGrD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,MAAM,CAAC,CA+CjB"}
1
+ {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../../src/generators/feed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAuGrD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,MAAM,CAAC,CA+CjB"}
@@ -9,7 +9,7 @@ function isHidden(filePath, settings) {
9
9
  if (pattern.startsWith("*") && basename.endsWith(pattern.slice(1)))
10
10
  return true;
11
11
  }
12
- if (basename.startsWith("_"))
12
+ if (basename.startsWith("_") || basename.startsWith("."))
13
13
  return true;
14
14
  return false;
15
15
  }
@@ -46,7 +46,14 @@ async function readDirRecursive(dirPath, rootDir, baseUrl, settings) {
46
46
  if (isNaN(date.getTime()))
47
47
  continue;
48
48
  const relativePath = "/" + path.relative(rootDir, fullPath).replace(/\\/g, "/");
49
- const urlPath = relativePath.replace(/\.(md|mdx)$/, "");
49
+ let urlPath = relativePath.replace(/\.(md|mdx)$/, "");
50
+ // Index files render at the directory URL; other docs are
51
+ // trailing-slash routes — both canonical clean-URL forms.
52
+ if (/^(readme|index)$/i.test(path.basename(urlPath))) {
53
+ urlPath = path.dirname(urlPath);
54
+ }
55
+ if (!urlPath.endsWith("/"))
56
+ urlPath += "/";
50
57
  const fullUrl = `${baseUrl.replace(/\/$/, "")}${urlPath}`;
51
58
  const title = parsed.data.title ||
52
59
  parsed.content.match(/^#\s+(.+)$/m)?.[1] ||
@@ -1 +1 @@
1
- {"version":3,"file":"feed.js","sourceRoot":"","sources":["../../src/generators/feed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feed.js","sourceRoot":"","sources":["../../src/generators/feed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Settings } from "../settings/index.js";
2
+ /**
3
+ * Generate robots.txt content.
4
+ *
5
+ * A non-empty `robots.txt` in the docs root always wins. Otherwise emit a
6
+ * permissive file; the `Sitemap:` line is only included when an absolute
7
+ * sitemap URL can be derived (`site.baseUrl`, or the request `origin`
8
+ * in serve mode) — relative Sitemap URLs are invalid per spec.
9
+ */
10
+ export declare function generateRobotsTxt(rootDir: string, settings: Settings, origin?: string): Promise<string>;
11
+ //# sourceMappingURL=robots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../../src/generators/robots.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGrD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
@@ -0,0 +1,32 @@
1
+ import path from "node:path";
2
+ import { promises as fs } from "node:fs";
3
+ import { buildSiteUrl } from "../seo/url.js";
4
+ /**
5
+ * Generate robots.txt content.
6
+ *
7
+ * A non-empty `robots.txt` in the docs root always wins. Otherwise emit a
8
+ * permissive file; the `Sitemap:` line is only included when an absolute
9
+ * sitemap URL can be derived (`site.baseUrl`, or the request `origin`
10
+ * in serve mode) — relative Sitemap URLs are invalid per spec.
11
+ */
12
+ export async function generateRobotsTxt(rootDir, settings, origin) {
13
+ const customRobotsPath = path.join(rootDir, "robots.txt");
14
+ try {
15
+ const customRobots = await fs.readFile(customRobotsPath, "utf-8");
16
+ if (customRobots.trim().length > 0) {
17
+ return customRobots;
18
+ }
19
+ }
20
+ catch {
21
+ // No custom robots.txt
22
+ }
23
+ const lines = ["User-agent: *", "Allow: /"];
24
+ if (settings.seo.generateSitemap) {
25
+ const siteUrl = buildSiteUrl(settings, origin);
26
+ if (siteUrl) {
27
+ lines.push(`Sitemap: ${siteUrl}sitemap.xml`);
28
+ }
29
+ }
30
+ return `${lines.join("\n")}\n`;
31
+ }
32
+ //# sourceMappingURL=robots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots.js","sourceRoot":"","sources":["../../src/generators/robots.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAe,EACf,QAAkB,EAClB,MAAe;IAEf,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC1D,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAClE,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,OAAO,YAAY,CAAC;QACtB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;IAC5C,IAAI,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/C,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,IAAI,CAAC,YAAY,OAAO,aAAa,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"search-index.d.ts","sourceRoot":"","sources":["../../src/generators/search-index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAsGD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAMxB"}
1
+ {"version":3,"file":"search-index.d.ts","sourceRoot":"","sources":["../../src/generators/search-index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAuGD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAMxB"}
@@ -9,7 +9,7 @@ function isHidden(filePath, settings) {
9
9
  if (pattern.startsWith("*") && basename.endsWith(pattern.slice(1)))
10
10
  return true;
11
11
  }
12
- if (basename.startsWith("_"))
12
+ if (basename.startsWith("_") || basename.startsWith("."))
13
13
  return true;
14
14
  return false;
15
15
  }
@@ -59,12 +59,13 @@ async function readDirRecursive(dirPath, rootDir, settings) {
59
59
  const parsed = matter(content);
60
60
  const relativePath = "/" + path.relative(rootDir, fullPath).replace(/\\/g, "/");
61
61
  let href = relativePath.replace(/\.(md|mdx)$/, "");
62
- // README becomes directory index, so link to the directory path
63
- if (path.basename(href).toLowerCase() === "readme") {
62
+ // Index files render at the directory URL; everything else is a
63
+ // trailing-slash doc route — both canonical clean-URL forms.
64
+ if (/^(readme|index)$/i.test(path.basename(href))) {
64
65
  href = path.dirname(href);
65
- if (!href.endsWith("/"))
66
- href += "/";
67
66
  }
67
+ if (!href.endsWith("/"))
68
+ href += "/";
68
69
  const title = parsed.data.title ||
69
70
  parsed.content.match(/^#\s+(.+)$/m)?.[1] ||
70
71
  item.name.replace(/\.\w+$/, "");
@@ -1 +1 @@
1
- {"version":3,"file":"search-index.js","sourceRoot":"","sources":["../../src/generators/search-index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-index.js","sourceRoot":"","sources":["../../src/generators/search-index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AAWjC,SAAS,QAAQ,CAAC,QAAgB,EAAE,QAAkB;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEzC,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACvD,IAAI,QAAQ,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QACtC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAChE,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO,OAAO;SACX,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,qBAAqB;SACnD,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,qBAAqB;SACpD,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,qBAAqB;SACjD,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC,6BAA6B;SACrE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,0BAA0B;SACjD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,uBAAuB;SAC5C,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,mBAAmB,CAAC;IAClC,IAAI,KAAK,CAAC;IACV,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,QAAkB;IACpD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;IAClD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC3C,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACvB,CAAC,CAAC,QAAQ,CAAC;IACb,OAAO,cAAc,GAAG,IAAI,CAAC;AAC/B,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,OAAe,EACf,OAAe,EACf,QAAkB;IAElB,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/C,IAAI,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;YAAE,SAAS;QAE3C,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;QAC9B,CAAC;aAAM,IACL,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACzB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EACpD,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACrD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC/B,MAAM,YAAY,GAChB,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC7D,IAAI,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;gBACnD,gEAAgE;gBAChE,6DAA6D;gBAC7D,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBAClD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC5B,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAAE,IAAI,IAAI,GAAG,CAAC;gBAErC,MAAM,KAAK,GACR,MAAM,CAAC,IAAI,CAAC,KAAgB;oBAC7B,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;oBACxC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAElC,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACnD,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAEjD,OAAO,CAAC,IAAI,CAAC;oBACX,KAAK;oBACL,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC;oBAClC,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;oBACnC,QAAQ;oBACR,OAAO,EAAE,YAAY;iBACtB,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,gCAAgC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,QAAkB;IAElB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC"}
@@ -1,3 +1,19 @@
1
1
  import type { Settings } from "../settings/index.js";
2
- export declare function generateSitemap(rootDir: string, settings: Settings): Promise<string>;
2
+ export interface SitemapPage {
3
+ urlPath: string;
4
+ lastmod?: string;
5
+ noIndex?: boolean;
6
+ }
7
+ /**
8
+ * Sitemap for the static-export path: consumes the same page list the
9
+ * exporter wrote, so output and sitemap always agree (including
10
+ * auto-index directory pages). Returns `null` without `site.baseUrl`.
11
+ */
12
+ export declare function generateSitemapFromPages(pages: SitemapPage[], settings: Settings, origin?: string): string | null;
13
+ /**
14
+ * Scan-based sitemap used by the dev server. `origin` is the request
15
+ * origin (`http://host:port`); `site.baseUrl` wins when configured.
16
+ * Returns `null` when no absolute base is available.
17
+ */
18
+ export declare function generateSitemap(rootDir: string, settings: Settings, origin?: string): Promise<string | null>;
3
19
  //# sourceMappingURL=sitemap.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../src/generators/sitemap.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AA+FrD,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,MAAM,CAAC,CA6BjB"}
1
+ {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../src/generators/sitemap.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGrD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAyED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,WAAW,EAAE,EACpB,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAGf;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKxB"}
@@ -1,6 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { promises as fs } from "node:fs";
3
3
  import matter from "gray-matter";
4
+ import { buildPageUrl } from "../seo/url.js";
4
5
  function isHidden(filePath, settings) {
5
6
  const basename = path.basename(filePath);
6
7
  for (const pattern of settings.files.extensions.hidden) {
@@ -9,75 +10,44 @@ function isHidden(filePath, settings) {
9
10
  if (pattern.startsWith("*") && basename.endsWith(pattern.slice(1)))
10
11
  return true;
11
12
  }
12
- if (basename.startsWith("_"))
13
+ if (basename.startsWith("_") || basename.startsWith("."))
13
14
  return true;
14
15
  return false;
15
16
  }
16
- async function readDirRecursive(dirPath, rootDir, baseUrl, settings) {
17
+ function toIsoDate(value) {
18
+ if (value == null || value === "")
19
+ return undefined;
20
+ const d = value instanceof Date ? value : new Date(String(value));
21
+ return Number.isNaN(d.getTime()) ? undefined : d.toISOString().split("T")[0];
22
+ }
23
+ /**
24
+ * Build sorted, deduped sitemap entries from page records. `noindex` pages
25
+ * are excluded and URLs are normalized + absolute. Returns `null` when no
26
+ * absolute base (`site.baseUrl` or `origin`) is available — a sitemap
27
+ * requires absolute URLs.
28
+ */
29
+ function buildEntries(pages, settings, origin) {
30
+ if (!settings.site.baseUrl && !origin)
31
+ return null;
32
+ const seen = new Set();
17
33
  const entries = [];
18
- const items = await fs.readdir(dirPath, { withFileTypes: true });
19
- for (const item of items) {
20
- const fullPath = path.join(dirPath, item.name);
21
- if (isHidden(fullPath, settings))
34
+ for (const page of pages) {
35
+ if (page.noIndex || settings.seo.noIndex)
22
36
  continue;
23
- if (item.isDirectory()) {
24
- const subEntries = await readDirRecursive(fullPath, rootDir, baseUrl, settings);
25
- entries.push(...subEntries);
26
- }
27
- else if (item.name.endsWith(".md") ||
28
- (item.name.endsWith(".mdx") && settings.mdx.enabled)) {
29
- try {
30
- const relativePath = "/" + path.relative(rootDir, fullPath).replace(/\\/g, "/");
31
- let urlPath = relativePath.replace(/\.(md|mdx)$/, "");
32
- // README files render at the directory index URL
33
- if (path.basename(urlPath).toLowerCase() === "readme") {
34
- const dirPath = path.dirname(urlPath);
35
- urlPath = dirPath === "/" ? "/" : `${dirPath}/`;
36
- }
37
- const fullUrl = `${baseUrl.replace(/\/$/, "")}${urlPath}`;
38
- // Try to get lastmod from frontmatter or file stat
39
- let lastmod;
40
- try {
41
- const content = await fs.readFile(fullPath, "utf-8");
42
- const parsed = matter(content);
43
- if (parsed.data.date) {
44
- const date = new Date(parsed.data.date);
45
- if (!isNaN(date.getTime())) {
46
- lastmod = date.toISOString().split("T")[0];
47
- }
48
- }
49
- }
50
- catch {
51
- // Fall through to file stat
52
- }
53
- if (!lastmod) {
54
- const stat = await fs.stat(fullPath);
55
- lastmod = stat.mtime.toISOString().split("T")[0];
56
- }
57
- entries.push({
58
- url: fullUrl,
59
- lastmod,
60
- changefreq: "weekly",
61
- });
62
- }
63
- catch {
64
- // Skip files that can't be read
65
- }
66
- }
37
+ const loc = buildPageUrl(page.urlPath, settings, origin);
38
+ if (!loc || seen.has(loc))
39
+ continue;
40
+ seen.add(loc);
41
+ entries.push({ loc, lastmod: page.lastmod, changefreq: "weekly" });
67
42
  }
43
+ entries.sort((a, b) => a.loc.localeCompare(b.loc));
68
44
  return entries;
69
45
  }
70
- export async function generateSitemap(rootDir, settings) {
71
- const baseUrl = settings.site.baseUrl || "http://localhost:1800";
72
- const basePath = settings.generate.basePath || "";
73
- const fullBaseUrl = baseUrl.replace(/\/$/, "") + basePath;
74
- const entries = await readDirRecursive(rootDir, rootDir, fullBaseUrl, settings);
75
- // Sort by URL for consistent output
76
- entries.sort((a, b) => a.url.localeCompare(b.url));
46
+ function renderXml(entries) {
77
47
  const urlElements = entries
78
48
  .map((entry) => ` <url>
79
- <loc>${escapeXml(entry.url)}</loc>
80
- <lastmod>${entry.lastmod}</lastmod>
49
+ <loc>${escapeXml(entry.loc)}</loc>
50
+ ${entry.lastmod ? `<lastmod>${entry.lastmod}</lastmod>` : ""}
81
51
  <changefreq>${entry.changefreq}</changefreq>
82
52
  </url>`)
83
53
  .join("\n");
@@ -86,6 +56,96 @@ export async function generateSitemap(rootDir, settings) {
86
56
  ${urlElements}
87
57
  </urlset>`;
88
58
  }
59
+ /**
60
+ * Sitemap for the static-export path: consumes the same page list the
61
+ * exporter wrote, so output and sitemap always agree (including
62
+ * auto-index directory pages). Returns `null` without `site.baseUrl`.
63
+ */
64
+ export function generateSitemapFromPages(pages, settings, origin) {
65
+ const entries = buildEntries(pages, settings, origin);
66
+ return entries ? renderXml(entries) : null;
67
+ }
68
+ /**
69
+ * Scan-based sitemap used by the dev server. `origin` is the request
70
+ * origin (`http://host:port`); `site.baseUrl` wins when configured.
71
+ * Returns `null` when no absolute base is available.
72
+ */
73
+ export async function generateSitemap(rootDir, settings, origin) {
74
+ const pages = [];
75
+ await scanDirectory(rootDir, rootDir, settings, pages);
76
+ const entries = buildEntries(pages, settings, origin);
77
+ return entries ? renderXml(entries) : null;
78
+ }
79
+ async function scanDirectory(dirPath, rootDir, settings, pages) {
80
+ const items = await fs.readdir(dirPath, { withFileTypes: true });
81
+ const subDirs = [];
82
+ let hasIndexFile = false;
83
+ const indexBaseNames = settings.files.indexFiles.map((name) => name.replace(/\.\w+$/, "").toLowerCase());
84
+ for (const item of items) {
85
+ const fullPath = path.join(dirPath, item.name);
86
+ if (isHidden(fullPath, settings))
87
+ continue;
88
+ if (item.isDirectory()) {
89
+ subDirs.push(fullPath);
90
+ continue;
91
+ }
92
+ if (!item.name.endsWith(".md") &&
93
+ !(item.name.endsWith(".mdx") && settings.mdx.enabled)) {
94
+ continue;
95
+ }
96
+ try {
97
+ const baseName = item.name.replace(/\.(md|mdx)$/i, "").toLowerCase();
98
+ const relDir = path.relative(rootDir, dirPath).replace(/\\/g, "/");
99
+ const dirUrl = relDir ? `/${relDir}/` : "/";
100
+ const urlPath = indexBaseNames.includes(baseName)
101
+ ? dirUrl
102
+ : `${dirUrl}${item.name.replace(/\.(md|mdx)$/i, "")}`;
103
+ if (indexBaseNames.includes(baseName))
104
+ hasIndexFile = true;
105
+ let lastmod;
106
+ let noIndex = false;
107
+ try {
108
+ const content = await fs.readFile(fullPath, "utf-8");
109
+ const parsed = matter(content);
110
+ lastmod = toIsoDate(parsed.data.dateModified ??
111
+ parsed.data.lastmod ??
112
+ parsed.data.updated ??
113
+ parsed.data.date);
114
+ noIndex = (parsed.data.noindex ?? parsed.data.noIndex) === true;
115
+ }
116
+ catch {
117
+ // Fall through to file stat
118
+ }
119
+ if (!lastmod) {
120
+ const stat = await fs.stat(fullPath);
121
+ lastmod = stat.mtime.toISOString().split("T")[0];
122
+ }
123
+ pages.push({ urlPath, lastmod, noIndex });
124
+ }
125
+ catch {
126
+ // Skip files that can't be read
127
+ }
128
+ }
129
+ // Auto-index directory page (directory without an index file)
130
+ if (!hasIndexFile) {
131
+ try {
132
+ const relDir = path.relative(rootDir, dirPath).replace(/\\/g, "/");
133
+ const urlPath = relDir ? `/${relDir}/` : "/";
134
+ const stat = await fs.stat(dirPath);
135
+ pages.push({
136
+ urlPath,
137
+ lastmod: stat.mtime.toISOString().split("T")[0],
138
+ noIndex: settings.seo.noIndexDirectoryPages,
139
+ });
140
+ }
141
+ catch {
142
+ // Skip directories that can't be stat'ed
143
+ }
144
+ }
145
+ for (const subDir of subDirs) {
146
+ await scanDirectory(subDir, rootDir, settings, pages);
147
+ }
148
+ }
89
149
  function escapeXml(text) {
90
150
  return text
91
151
  .replace(/&/g, "&amp;")