serve-my-md 1.1.6 → 1.1.8

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/bin/index.js CHANGED
@@ -12,12 +12,12 @@ var Logger = class {
12
12
 
13
13
  // cli/src/shared.ts
14
14
  import MarkdownIt from "markdown-it";
15
- import path2 from "path";
15
+ import path3 from "path";
16
16
  import Prism from "prismjs";
17
17
 
18
18
  // cli/src/core/index.ts
19
- import fs2 from "fs/promises";
20
- import path from "path";
19
+ import fs3 from "fs/promises";
20
+ import path2 from "path";
21
21
  import { minimatch } from "minimatch";
22
22
 
23
23
  // cli/src/utils/index.ts
@@ -114,6 +114,8 @@ var config_default = {
114
114
 
115
115
  // cli/src/lib/commander.ts
116
116
  import { Command } from "commander";
117
+ import path from "path";
118
+ import fs2 from "fs";
117
119
  var program = new Command();
118
120
  program.name(config_default.name).description(config_default.description).version(config_default.version);
119
121
  program.option("-d, --directory <path>", "Directory to scan for markdown files", ".");
@@ -130,6 +132,11 @@ if (options.interactive || options.directory === void 0) {
130
132
  });
131
133
  options.directory = res.trim();
132
134
  }
135
+ options.directory = path.resolve(options.directory);
136
+ fs2.existsSync(options.directory) || (() => {
137
+ console.error("Directory does not exist: " + options.directory);
138
+ process.exit(1);
139
+ })();
133
140
 
134
141
  // cli/src/core/index.ts
135
142
  import { readdirSync } from "fs";
@@ -143,7 +150,7 @@ var constants_default = {
143
150
  var STATIC_TEMP_CONTENT_PREFIX = constants_default.STATIC_TEMP_CONTENT_PREFIX;
144
151
  async function readConfig(filepath) {
145
152
  try {
146
- const data = JSON.parse(await fs2.readFile(filepath, "utf-8"));
153
+ const data = JSON.parse(await fs3.readFile(filepath, "utf-8"));
147
154
  return data;
148
155
  } catch (err) {
149
156
  Logger.log(
@@ -166,7 +173,7 @@ async function parseSmmIgnore(filePath) {
166
173
  return ignored;
167
174
  };
168
175
  var shouldIgnore2 = shouldIgnore3;
169
- const raw = await fs2.readFile(filePath, "utf8");
176
+ const raw = await fs3.readFile(filePath, "utf8");
170
177
  const rules = raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#")).map((line) => {
171
178
  const negated = line.startsWith("!");
172
179
  const pattern = negated ? line.slice(1) : line;
@@ -185,11 +192,11 @@ async function parseSmmIgnore(filePath) {
185
192
  }
186
193
  }
187
194
  async function getMarkdownFiles(baseUrl, pairChildren) {
188
- const files = await fs2.readdir(baseUrl, { withFileTypes: true });
195
+ const files = await fs3.readdir(baseUrl, { withFileTypes: true });
189
196
  const routeTree = pairChildren || [];
190
197
  const promises = [];
191
198
  for (const file of files) {
192
- const filePath = path.join(baseUrl, file.name);
199
+ const filePath = path2.join(baseUrl, file.name);
193
200
  if (shouldIgnore(filePath.slice(options.directory.length)) || filePath.slice(options.directory.length) === finalConfig.publicPath)
194
201
  continue;
195
202
  if (file.isDirectory()) {
@@ -247,16 +254,16 @@ function getPath(filepath) {
247
254
  return slugify(transformedPath).split("/").filter((s) => !(s.startsWith("(") && s.endsWith(")"))).join("/") || "/";
248
255
  }
249
256
  async function parseMD(filepath) {
250
- const path4 = getPath(filepath);
257
+ const path5 = getPath(filepath);
251
258
  return {
252
- path: path4,
253
- content: mdParser.render(await fs2.readFile(filepath, "utf-8"))
259
+ path: path5,
260
+ content: mdParser.render(await fs3.readFile(filepath, "utf-8"))
254
261
  };
255
262
  }
256
263
  async function generateHtml(distDir, routeContent) {
257
264
  try {
258
- let htmlTemplate = await fs2.readFile(
259
- path.join(import.meta.dirname, "..", "index.html"),
265
+ let htmlTemplate = await fs3.readFile(
266
+ path2.join(import.meta.dirname, "..", "index.html"),
260
267
  "utf-8"
261
268
  );
262
269
  const commentStart = htmlTemplate.indexOf("<!--");
@@ -268,20 +275,20 @@ async function generateHtml(distDir, routeContent) {
268
275
  ""
269
276
  );
270
277
  if (distDir) {
271
- const files = readdirSync(path.join(distDir, "assets"));
278
+ const files = readdirSync(path2.join(distDir, "assets"));
272
279
  const cssFile = files.find((file) => file.endsWith(".css"));
273
280
  const jsFile = files.find((file) => file.endsWith(".js"));
274
- const prefix = distDir.slice(path.join(import.meta.dirname, options.directory).length);
281
+ const prefix = distDir.slice(path2.join(import.meta.dirname, options.directory).length);
275
282
  htmlTemplate = htmlTemplate.replace(`<script type="module" src="/src/main.tsx"></script>`, "");
276
283
  if (cssFile && jsFile) {
277
284
  htmlTemplate = htmlTemplate.replace(
278
285
  "{{distAssets}}",
279
- `<link rel="stylesheet" href="${path.join(
286
+ `<link rel="stylesheet" href="${path2.join(
280
287
  prefix,
281
288
  "assets",
282
289
  cssFile
283
290
  )}" />
284
- <script type="module" src="${path.join(
291
+ <script type="module" src="${path2.join(
285
292
  prefix,
286
293
  "assets",
287
294
  jsFile
@@ -315,19 +322,19 @@ async function buildDistRoutesFromRouteTree(routeTree, groupedRoutes, distPath,
315
322
  prefix
316
323
  );
317
324
  } else {
318
- const distRoutePath = path.join(distPath, prefix, node.pathSegment.replace("/", "")) + (node.pathSegment === "" ? "/index.html" : ".html");
319
- await fs2.mkdir(path.dirname(distRoutePath), { recursive: true });
325
+ const distRoutePath = path2.join(distPath, prefix, node.pathSegment.replace("/", "")) + (node.pathSegment === "" ? "/index.html" : ".html");
326
+ await fs3.mkdir(path2.dirname(distRoutePath), { recursive: true });
320
327
  const html = await generateHtml(
321
328
  distPath,
322
- groupedRoutes[path.posix.join(prefix, node.pathSegment)]?.[0]?.content
329
+ groupedRoutes[path2.posix.join(prefix, node.pathSegment)]?.[0]?.content
323
330
  );
324
- await fs2.writeFile(distRoutePath, html, "utf-8");
331
+ await fs3.writeFile(distRoutePath, html, "utf-8");
325
332
  if (node.children) {
326
333
  await buildDistRoutesFromRouteTree(
327
334
  node.children,
328
335
  groupedRoutes,
329
336
  distPath,
330
- path.join(prefix, node.pathSegment)
337
+ path2.join(prefix, node.pathSegment)
331
338
  );
332
339
  }
333
340
  }
@@ -362,11 +369,11 @@ import MarkdownItFootNote from "markdown-it-footnote";
362
369
  import MarkdownItTasks from "markdown-it-task-lists";
363
370
  import loadLanguages from "prismjs/components/index.js";
364
371
  var { shouldIgnore } = await parseSmmIgnore(
365
- path2.join(options.directory, config_default.defaultIgnorePath)
372
+ path3.join(options.directory, config_default.defaultIgnorePath)
366
373
  );
367
374
  var finalConfig = {
368
375
  ...smm_config_default,
369
- ...await readConfig(path2.join(options.directory, config_default.defaultConfigPath))
376
+ ...await readConfig(path3.join(options.directory, config_default.defaultConfigPath))
370
377
  };
371
378
  var md = new MarkdownIt({
372
379
  ...finalConfig.markdownItOptions,
@@ -383,7 +390,7 @@ var mdParser = md;
383
390
 
384
391
  // cli/src/core/build.ts
385
392
  import { cp, readdir as readdir2, rm, writeFile } from "fs/promises";
386
- import path3, { resolve } from "path";
393
+ import path4, { resolve } from "path";
387
394
  import { fileURLToPath } from "url";
388
395
  import { build as viteBuild } from "vite";
389
396
  import { mkdirSync } from "fs";
@@ -398,7 +405,7 @@ async function build(options2) {
398
405
  const parsePromises = [];
399
406
  Logger.log("Processing routes...");
400
407
  for (const file of makeRoutesOfNestedPathsRaw(routeTree)) {
401
- parsePromises.push(parseMD(path3.join(options2.directory, file)));
408
+ parsePromises.push(parseMD(path4.join(options2.directory, file)));
402
409
  }
403
410
  cleanNestedPaths(routeTree);
404
411
  const groupedRoutes = Object.groupBy(
@@ -406,7 +413,13 @@ async function build(options2) {
406
413
  (route) => route.path
407
414
  );
408
415
  const routes = makeRoutesOfNestedPaths(routeTree).reduce(
409
- (acc, pth) => [...acc, ...(groupedRoutes[pth] ?? []).map((r) => ({ ...r, path: path3.join(finalConfig.baseRoute || "/", r.path) }))],
416
+ (acc, pth) => [
417
+ ...acc,
418
+ ...(groupedRoutes[pth] ?? []).map((r) => ({
419
+ ...r,
420
+ path: path4.join(finalConfig.baseRoute || "/", r.path)
421
+ }))
422
+ ],
410
423
  []
411
424
  );
412
425
  const out = {
@@ -429,37 +442,37 @@ async function build(options2) {
429
442
  routes.forEach((o) => {
430
443
  Logger.log(o.path);
431
444
  });
432
- const __dirname = path3.dirname(fileURLToPath(import.meta.url));
433
- const webDir = path3.join(__dirname, "..", WEB_DIRNAME);
434
- const distDir = path3.join(webDir, DIST_DIRNAME);
435
- mkdirSync(path3.join(webDir, "src", ".generated"), { recursive: true });
445
+ const __dirname = path4.dirname(fileURLToPath(import.meta.url));
446
+ const webDir = path4.join(__dirname, "..", WEB_DIRNAME);
447
+ const distDir = path4.join(webDir, DIST_DIRNAME);
448
+ mkdirSync(path4.join(webDir, "src", ".generated"), { recursive: true });
436
449
  await writeFile(
437
- path3.join(webDir, "src", ".generated", "output.json"),
450
+ path4.join(webDir, "src", ".generated", "output.json"),
438
451
  JSON.stringify(out)
439
452
  );
440
453
  await writeFile(
441
- path3.join(webDir, "src", ".generated", "paths.json"),
454
+ path4.join(webDir, "src", ".generated", "paths.json"),
442
455
  JSON.stringify(routeTree)
443
456
  );
444
457
  Logger.log("\nParsed MDs");
445
- await writeFile(path3.join(webDir, "index.html"), await generateHtml());
458
+ await writeFile(path4.join(webDir, "index.html"), await generateHtml());
446
459
  Logger.log("Generated HTML from template");
447
460
  if (!skipBuild) {
448
- const entries = await readdir2(path3.join(webDir, PUBLIC_DIRNAME));
461
+ const entries = await readdir2(path4.join(webDir, PUBLIC_DIRNAME));
449
462
  for (const entry of entries) {
450
- await rm(path3.join(webDir, PUBLIC_DIRNAME, entry), {
463
+ await rm(path4.join(webDir, PUBLIC_DIRNAME, entry), {
451
464
  recursive: true,
452
465
  force: true
453
466
  });
454
467
  }
455
468
  if (finalConfig.publicPath) {
456
469
  if (await FileOrDirectoryExists(
457
- path3.join(options2.directory, finalConfig.publicPath)
470
+ path4.join(options2.directory, finalConfig.publicPath)
458
471
  )) {
459
472
  Logger.log(`Copying public assets from ${finalConfig.publicPath}...`);
460
473
  await cp(
461
- path3.join(options2.directory, finalConfig.publicPath),
462
- path3.join(webDir, PUBLIC_DIRNAME),
474
+ path4.join(options2.directory, finalConfig.publicPath),
475
+ path4.join(webDir, PUBLIC_DIRNAME),
463
476
  { recursive: true }
464
477
  );
465
478
  } else {
@@ -471,7 +484,7 @@ async function build(options2) {
471
484
  configFile: resolve(webDir, "vite.config.ts")
472
485
  });
473
486
  await buildDistRoutesFromRouteTree(routeTree, groupedRoutes, distDir);
474
- const targetDist = path3.join(options2.directory, DIST_DIRNAME);
487
+ const targetDist = path4.join(options2.directory, DIST_DIRNAME);
475
488
  await rm(targetDist, { recursive: true }).catch(() => {
476
489
  });
477
490
  Logger.log("Built the app, copying results...");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serve-my-md",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "type": "module",
5
5
  "description": "Generate beautiful SEO-friendly static websites from Markdown files.",
6
6
  "repository": {
package/web/index.html CHANGED
@@ -7,15 +7,14 @@
7
7
  <meta name="theme-color" content="#000000" />
8
8
  <meta
9
9
  name="description"
10
- content="A fixture for testing ghostly operations in SMM."
10
+ content="Docs for serve-my-md."
11
11
  />
12
- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sorts+Mill+Goudy:ital@0;1&display=swap" /><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" />
13
- <meta property="og:title" content="SMM Ghostly Fixture">
14
- <meta property="og:description" content="A fixture for testing ghostly operations in SMM.">
15
- <meta property="og:site_name" content="SMM Ghostly Store">
16
- <meta property="og:determiner" content="the">
17
- <meta property="og:image" content="/og-image.png">
18
- <title>SMM Ghostly Fixture</title>
12
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Exo:ital,wght@0,100..900;1,100..900&display=swap" /><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Commissioner:wght@100..900&display=swap" /><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&display=swap" />
13
+ <meta property="og:title" content="Serve My MD Docs">
14
+ <meta property="og:description" content="Documentation for serve-my-md, a CLI tool to generate static docs sites from markdown.">
15
+ <meta property="og:type" content="website">
16
+ <meta property="og:site_name" content="Serve My MD Docs">
17
+ <title>Serve My MD Docs</title>
19
18
 
20
19
 
21
20
  <style>
@@ -1 +1 @@
1
- {"rootTitle":"SMM Ghostly Fixture","description":"A fixture for testing ghostly operations in SMM.","baseRoute":"/","defaultTheme":"light","name":"Ghostly Store","showNameWithLogo":true,"routes":[{"path":"/","content":"<h1>hello this is main md</h1>\n<p><a href=\"/features\">features</a></p>\n"},{"path":"/features","content":"<h1>features</h1>\n<p>browse features:</p>\n<ul>\n<li><a href=\"/features/coffee\">coffee</a></li>\n<li><a href=\"/features/tea\">tea</a></li>\n<li><a href=\"/features/choorma\">choorma</a></li>\n<li><a href=\"/features/ghee-dudh\">ghee dudh</a></li>\n</ul>\n"},{"path":"/features/choorma","content":"<h1>choorma khao body bnao</h1>\n<p>price: nani dedo 10 minute choorma bnane ke liye :moon:</p>\n"},{"path":"/features/coffee","content":"<h1>co-fee</h1>\n<p>price: $2</p>\n"},{"path":"/features/ghee-dudh","content":"<h1>ghee dudh kha ladle</h1>\n<p>price: 1 lakh de bhais le</p>\n"},{"path":"/features/tea","content":"<h1>tea-tty</h1>\n<p>price: $69</p>\n"},{"path":"/muah","content":"<h1>Markdown Feature Showcase</h1>\n<h2>Headings</h2>\n<h1>H1 Heading</h1>\n<h2>H2 Heading</h2>\n<h3>H3 Heading</h3>\n<h4>H4 Heading</h4>\n<hr />\n<h2>Text Styles</h2>\n<ul>\n<li><em>Italic</em></li>\n<li><strong>Bold</strong></li>\n<li><em><strong>Bold Italic</strong></em></li>\n<li><s>Strikethrough</s></li>\n</ul>\n<hr />\n<h2>Links</h2>\n<p><a href=\"https://openai.com\">OpenAI</a></p>\n<hr />\n<h2>Images</h2>\n<p><img src=\"https://thumbs.dreamstime.com/b/fearsome-ancient-spartan-warrior-greece-red-cloak-spartan-helmet-night-spartan-movie-scene-action-sequence-spartan-helmet-284208996.jpg?w=360\" alt=\"Placeholder\" /></p>\n<hr />\n<h2>Blockquote</h2>\n<blockquote>\n<p>This is a blockquote example.<br />\nIt spans multiple lines.</p>\n</blockquote>\n<hr />\n<h2>Code (using indentation, not backticks)</h2>\n<p>Inline code example: <code>print(&quot;Hello World&quot;)</code></p>\n<pre class=\"language-python\"><code class=\"language-python\"> <span class=\"token keyword\">def</span> <span class=\"token function\">greet</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n <span class=\"token keyword\">return</span> <span class=\"token string\">\"Hello \"</span> <span class=\"token operator\">+</span> name\n\n <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>greet<span class=\"token punctuation\">(</span><span class=\"token string\">\"Markdown\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n</code></pre>\n<hr />\n<h2>Lists</h2>\n<h3>Unordered List</h3>\n<ul>\n<li>Item A</li>\n<li>Item B\n<ul>\n<li>Subitem B1</li>\n<li>Subitem B2</li>\n</ul>\n</li>\n</ul>\n<h3>Ordered List</h3>\n<ol>\n<li>Step One</li>\n<li>Step Two</li>\n<li>Step Three</li>\n</ol>\n<hr />\n<h2>Checkboxes</h2>\n<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input class=\"task-list-item-checkbox\" checked=\"\" disabled=\"\" type=\"checkbox\"> Completed</li>\n<li class=\"task-list-item\"><input class=\"task-list-item-checkbox\" disabled=\"\" type=\"checkbox\"> Not Completed</li>\n<li class=\"task-list-item\"><input class=\"task-list-item-checkbox\" disabled=\"\" type=\"checkbox\"> Pending</li>\n</ul>\n<hr />\n<h2>Table</h2>\n<table>\n<thead>\n<tr>\n<th>Product</th>\n<th>Price</th>\n<th>In Stock</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Apple</td>\n<td>$1</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Banana</td>\n<td>$0.5</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Orange</td>\n<td>$0.8</td>\n<td>Yes</td>\n</tr>\n</tbody>\n</table>\n<hr />\n<h2>Horizontal Rule</h2>\n<hr />\n<hr />\n<h2>Emoji</h2>\n<p>😀 🚀 🎉 ❤️🔥</p>\n<hr />\n<h2>Footnotes</h2>\n<p>This is a sentence with a footnote.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup></p>\n<hr />\n<h2>HTML Support</h2>\n<div style=\"color: green;\">This line uses HTML styling.</div>\n<hr />\n<h2>Done Checklist</h2>\n<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input class=\"task-list-item-checkbox\" checked=\"\" disabled=\"\" type=\"checkbox\"> Includes tables</li>\n<li class=\"task-list-item\"><input class=\"task-list-item-checkbox\" checked=\"\" disabled=\"\" type=\"checkbox\"> Includes checkboxes</li>\n<li class=\"task-list-item\"><input class=\"task-list-item-checkbox\" checked=\"\" disabled=\"\" type=\"checkbox\"> Includes code (indent-based)</li>\n<li class=\"task-list-item\"><input class=\"task-list-item-checkbox\" checked=\"\" disabled=\"\" type=\"checkbox\"> Includes emojis</li>\n<li class=\"task-list-item\"><input class=\"task-list-item-checkbox\" checked=\"\" disabled=\"\" type=\"checkbox\"> Includes all Markdown features</li>\n</ul>\n<hr class=\"footnotes-sep\" />\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>This is the footnote explanation. <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n"},{"path":"/zaram-chand","content":"<h1>Mohandas Karam Chand Gandhi</h1>\n<p>He was also known as Mahatma Gandhi Thaave Aandhi.</p>\n"},{"path":"/tos","content":"<h1>Terms of Services</h1>\n<p>We only serve people with a knack for cooking. If you don't cook, you're not welcome.</p>\n"}],"outDir":"dist","fonts":{"title":"Sorts Mill Goudy","body":"Montserrat","mono":"monospace"},"version":"1.0.0 LTS"}
1
+ {"rootTitle":"Serve My MD Docs","description":"Docs for serve-my-md.","baseRoute":"/","defaultTheme":"dark","name":"Serve My MD","showNameWithLogo":true,"routes":[{"path":"/","content":"<h1>serve-my-md Docs</h1>\n<p>Welcome to the docs for <code>serve-my-md</code>.</p>\n<p>A tiny CLI to generate a static docs website from markdown files.</p>\n<ul>\n<li><a href=\"/why-serve-my-md\">Why serve-my-md?</a></li>\n<li><a href=\"/getting-started\">Getting Started</a></li>\n<li><a href=\"/cli-reference\">CLI Reference</a></li>\n<li><a href=\"/key-behaviors\">Key Behaviors</a></li>\n</ul>\n<h3>Guide</h3>\n<ul>\n<li><a href=\"/routing-and-sidebar-patterns\">Routing and Sidebar Patterns</a></li>\n<li><a href=\"/markdown-and-rendering\">Markdown and Rendering</a></li>\n<li><a href=\"/build-output-and-assets\">Build Output and Assets</a></li>\n</ul>\n<h3>Configuration</h3>\n<ul>\n<li><a href=\"/smm-config\">SMM Config</a></li>\n<li><a href=\"/smm-ignore\">SMM Ignore</a></li>\n</ul>\n<h3>Examples</h3>\n<ul>\n<li><a href=\"/structure-examples\">Structure Examples</a></li>\n<li><a href=\"/config-examples\">Config Examples</a></li>\n</ul>\n<h2>Future goals</h2>\n<ul>\n<li><strong>Search Indexing</strong> — structured search index for smarter results</li>\n<li><strong>Config validation</strong> — Zod-based schema validation of <code>smm.config.json</code> with JSON Schema export</li>\n<li><strong>Sitemap</strong> — automatic <code>sitemap.xml</code> generation</li>\n<li><strong>Per-page Open Graph</strong> — page-level og tags from frontmatter</li>\n<li><strong>Doctor command</strong> — health checks: config validation, route discovery, broken link detection, and more</li>\n<li><strong>Link validation</strong> — flag invalid internal links at build-time</li>\n<li><strong>Optional RSS</strong> — config-enableable RSS feed for blog/changelog content</li>\n<li><strong>SchemaStore upload</strong> — publish JSON Schema to SchemaStore once stable</li>\n</ul>\n"},{"path":"/getting-started","content":"<h1>Getting Started</h1>\n<h2>Install</h2>\n<pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> i <span class=\"token parameter variable\">-g</span> serve-my-md\n</code></pre>\n<h2>Run</h2>\n<pre class=\"language-bash\"><code class=\"language-bash\">serve-my-md <span class=\"token parameter variable\">--directory</span> <span class=\"token builtin class-name\">.</span>\n</code></pre>\n<p>The CLI scans markdown files in the target directory and generates a static website there. Every page is a standalone HTML file (SSG) — deploy to any static host or CDN.</p>\n<h2>What gets read automatically</h2>\n<ul>\n<li><code>smm.config.json</code> at docs root (if present)</li>\n<li><code>.smmignore</code> at docs root (if present)</li>\n<li>fallback to built-in defaults when these files are missing</li>\n</ul>\n<h2>Important <code>index.md</code> behavior</h2>\n<ul>\n<li><code>index.md</code> is the landing page for its directory.</li>\n<li><code>index</code> is never included in the pathname.</li>\n<li>Internally, an <code>index.md</code> entry is treated as <code>&quot;&quot;</code> (empty string) in route tree naming.</li>\n</ul>\n<p>Example:</p>\n<pre class=\"language-text\"><code class=\"language-text\">docs/\n index.md\n guides/\n index.md\n install.md\n</code></pre>\n<p>Routes:</p>\n<ul>\n<li><code>/</code></li>\n<li><code>/guides</code></li>\n<li><code>/guides/install</code></li>\n</ul>\n<h2>Future goals</h2>\n<ul>\n<li><strong>Search Indexing</strong> — structured search index for smarter results</li>\n<li><strong>Config validation</strong> — Zod-based schema validation of <code>smm.config.json</code> with JSON Schema export</li>\n<li><strong>Sitemap</strong> — automatic <code>sitemap.xml</code> generation</li>\n<li><strong>Per-page Open Graph</strong> — page-level og tags from frontmatter</li>\n<li><strong>Doctor command</strong> — health checks: config validation, route discovery, broken link detection, and more</li>\n<li><strong>Link validation</strong> — flag invalid internal links at build-time</li>\n<li><strong>Optional RSS</strong> — config-enableable RSS feed for blog/changelog content</li>\n<li><strong>SchemaStore upload</strong> — publish JSON Schema to SchemaStore once stable</li>\n</ul>\n"},{"path":"/cli-reference","content":"<h1>CLI Reference</h1>\n<h2>Main command</h2>\n<ul>\n<li><code>serve-my-md</code>: build a static docs website from markdown files.</li>\n</ul>\n<h2>Options</h2>\n<ul>\n<li><code>-d, --directory &lt;path&gt;</code>: docs root path (default <code>.</code>).</li>\n<li><code>-i, --interactive</code>: prompt for docs root.</li>\n</ul>\n<h2>Build output (SSG)</h2>\n<p>The CLI generates a fully static site:</p>\n<ul>\n<li>Each route gets its own <code>.html</code> file with pre-rendered markdown content in the HTML</li>\n<li>Assets (CSS, JS) are built via Vite and placed under <code>dist/assets/</code></li>\n<li>The final <code>dist/</code> directory is copied to your docs root — ready to deploy</li>\n</ul>\n<h2>Config and ignore loading</h2>\n<ul>\n<li>Loads config from <code>./smm.config.json</code> relative to target directory.</li>\n<li>Loads ignore rules from <code>./.smmignore</code> relative to target directory.</li>\n<li>If <code>publicPath</code> is set in config, copies that directory into app public assets before build.</li>\n</ul>\n<h2>Markdown pipeline</h2>\n<ul>\n<li>Uses markdown-it with task lists and footnotes plugins enabled.</li>\n<li>Prism.js syntax highlighting with auto-loading for unknown languages.</li>\n<li>Generates OG/meta/font tags in HTML from config values.</li>\n</ul>\n<h2>Runtime/navigation behaviors</h2>\n<ul>\n<li>Markdown links with non-HTTP hrefs are intercepted and navigated client-side.</li>\n<li>Intent-based link preloading for faster navigation.</li>\n<li>Keyboard shortcuts:\n<ul>\n<li>Search: <code>Ctrl+Shift+F</code></li>\n<li>Next page: <code>Alt+Enter</code></li>\n<li>Previous page: <code>Alt+Shift+Enter</code></li>\n</ul>\n</li>\n<li>Search returns matches in current page and across other pages.</li>\n</ul>\n<h2>Test-only option</h2>\n<ul>\n<li><code>--skip-build</code> exists only in vitest mode, not in normal CLI usage.</li>\n</ul>\n<h2>Future goals</h2>\n<ul>\n<li><strong>Search Indexing</strong> — structured search index for smarter results</li>\n<li><strong>Config validation</strong> — Zod-based schema validation of <code>smm.config.json</code> with JSON Schema export</li>\n<li><strong>Sitemap</strong> — automatic <code>sitemap.xml</code> generation</li>\n<li><strong>Per-page Open Graph</strong> — page-level og tags from frontmatter</li>\n<li><strong>Doctor command</strong> — health checks: config validation, route discovery, broken link detection, and more</li>\n<li><strong>Link validation</strong> — flag invalid internal links at build-time</li>\n<li><strong>Optional RSS</strong> — config-enableable RSS feed for blog/changelog content</li>\n<li><strong>SchemaStore upload</strong> — publish JSON Schema to SchemaStore once stable</li>\n</ul>\n"},{"path":"/key-behaviors","content":"<h1>Key Behaviors</h1>\n<h2>Internal links auto-prepend <code>baseRoute</code></h2>\n<p>When you set a <code>baseRoute</code> in <code>smm.config.json</code> (e.g. <code>/docs</code>), any internal markdown link (<code>[text](/some-page)</code>) automatically has that base prepended during navigation. You never need to manually prefix links with the base route — change it in one place and all links adapt.</p>\n<h2>Sorting and indexing</h2>\n<p>Pages, directories, and groupers are sorted automatically when <code>sortRoutes: true</code>:</p>\n<ol>\n<li><code>index.md</code> always comes first.</li>\n<li>Regular files and directories come next, sorted lexicographically.</li>\n<li>Groupers <code>(Name)</code> come last, after all regular items.</li>\n</ol>\n<p>Numeric prefixes on filenames (<code>1. intro.md</code>, <code>2. setup.md</code>) control ordering within each tier. The prefix is stripped from the emitted URL when <code>trimIndexFromPath: true</code>.</p>\n<p>Grouper indexes only affect order among other groupers — they never collide with file/directory indexes since groupers always sort after regular items.</p>\n<h2>SSG pre-rendering</h2>\n<p>Every page is a standalone <code>.html</code> file with pre-rendered markdown content baked into the DOM. Search engines see the full content immediately. After the page loads, the React SPA hydrates and takes over for seamless client-side navigation.</p>\n<h2>Groupers</h2>\n<p>Directories named <code>(Name)</code> act as groupers:</p>\n<ul>\n<li>Rendered as a labeled section in the sidebar (not collapsible).</li>\n<li>Skipped from URL pathnames — files inside sit at the grouper's parent URL level.</li>\n<li>Cannot contain <code>index.md</code>.</li>\n<li>Can be ordered with numeric prefixes: <code>(1. Guide)</code>, <code>(2. Reference)</code>.</li>\n</ul>\n<h2>Client-side link interception</h2>\n<p>Internal markdown links (<code>[text](/path)</code>) are intercepted by the SPA router — navigating them does not cause a full page reload. External links (<code>https://...</code>) open normally.</p>\n<h2>Intent-based preloading</h2>\n<p>When you hover over or touch a link, its content is preloaded in the background. Navigation feels instant because the data is ready before you click.</p>\n<h2>Auto-slug generation</h2>\n<p>Route path segments are automatically normalized:</p>\n<ul>\n<li>Lowercased</li>\n<li>Spaces and underscores become <code>-</code></li>\n<li>Punctuation (<code>.,;&quot;'\\\\:&lt;&gt;</code>?!`) is removed</li>\n<li>Grouper directory names like <code>(Group)</code> are excluded entirely</li>\n</ul>\n<p>No need to manually craft URL-safe filenames.</p>\n<h2><code>index.md</code> as landing page</h2>\n<ul>\n<li><code>index.md</code> represents the landing page for its directory.</li>\n<li>It is never included in the URL pathname — internally maps to <code>&quot;&quot;</code>.</li>\n<li>If a directory contains only <code>index.md</code> and no other files, it collapses to a leaf node (no collapsible).</li>\n</ul>\n<h2><code>publicPath</code> auto-copy and auto-exclude</h2>\n<p>If <code>publicPath</code> is set in config, that directory is:</p>\n<ul>\n<li>Copied into the web app's public assets before the Vite build.</li>\n<li>Automatically excluded from markdown scanning — no need to also add it to <code>.smmignore</code>.</li>\n</ul>\n<h2>Config merge with sensible defaults</h2>\n<p><code>smm.config.json</code> is merged over built-in defaults. You only need to specify what you want to override. Missing options fall back to the CLI's internal defaults — the config file is entirely optional.</p>\n<h2><code>.smmignore</code> glob patterns</h2>\n<p>Create <code>.smmignore</code> at your docs root to exclude paths during markdown traversal:</p>\n<ul>\n<li>Lines starting with <code>#</code> are comments.</li>\n<li>Empty lines are ignored.</li>\n<li>Prefix with <code>!</code> to un-ignore.</li>\n<li>Patterns are evaluated top-to-bottom, last match wins.</li>\n</ul>\n"},{"path":"/why-serve-my-md","content":"<h1>Why serve-my-md?</h1>\n<h2>Zero-friction static site</h2>\n<p>serve-my-md generates a <strong>completely static site</strong> — every page is a standalone HTML file with pre-rendered content. No server, no database, no build-time backend. Deploy anywhere: CDN, GitHub Pages, Netlify, Vercel, S3, or a simple static file server.</p>\n<h2>Blazing fast</h2>\n<p>Static HTML means instant first paint. After load, the React SPA takes over for seamless client-side navigation with intent-based preloading.</p>\n<h2>Rich markdown support</h2>\n<ul>\n<li>Full markdown-it pipeline with footnotes, task lists, and configurable options</li>\n<li>Prism.js syntax highlighting for dozens of languages</li>\n<li>Configurable markdown-it options via <code>smm.config.json</code></li>\n</ul>\n<h2>Custom ordering</h2>\n<p>Control your page order with numeric filename prefixes:</p>\n<pre class=\"language-text\"><code class=\"language-text\">1. intro.md\n2. setup.md\n3. advanced.md\n</code></pre>\n<p>Set <code>trimIndexFromPath: true</code> in config and the prefixes are stripped from URLs while ordering is preserved.</p>\n<h2>Minimal yet powerful config</h2>\n<p>A single <code>smm.config.json</code> at your docs root is all you need. Override titles, theme, fonts, Open Graph tags, and more — or use the sensible defaults and get going immediately.</p>\n<h2>SEO built-in</h2>\n<p>Every page is a full HTML document with:</p>\n<ul>\n<li>Unique <code>&lt;title&gt;</code> and <code>&lt;meta description&gt;</code></li>\n<li>Open Graph tags for social previews</li>\n<li>Pre-rendered content in the HTML — search engines see everything</li>\n<li>Semantic HTML structure</li>\n</ul>\n<h2>Great user experience</h2>\n<ul>\n<li><strong>Site-wide search</strong> — instant full-text search with keyboard shortcut (Ctrl+Shift+F)</li>\n<li><strong>Accessibility</strong> — keyboard navigation, ARIA labels, semantic landmarks</li>\n<li><strong>Light/dark themes</strong> — automatic or user-toggleable</li>\n<li><strong>Responsive</strong> — works on desktop and mobile</li>\n<li><strong>Breadcrumbs</strong> — clear navigation context</li>\n<li><strong>Keyboard shortcuts</strong> — quick navigation between pages</li>\n</ul>\n"},{"path":"/routing-and-sidebar-patterns","content":"<h1>Routing and Sidebar Patterns</h1>\n<h2><code>index.md</code> is landing page</h2>\n<ul>\n<li><code>index.md</code> represents the landing page for its directory.</li>\n<li><code>index</code> is not part of URL pathnames.</li>\n<li>In nested name handling, <code>index.md</code> maps to <code>&quot;&quot;</code> (empty string).</li>\n<li>If a directory contains only an <code>index.md</code> and no other files, the directory collapses to a leaf node (no collapsible in sidebar).</li>\n</ul>\n<h2>Grouping directories with parentheses (groupers)</h2>\n<p>Directory names wrapped in <code>()</code> act as <strong>groupers</strong>:</p>\n<ul>\n<li>shown as a labeled section in the sidebar (not collapsible)</li>\n<li>skipped from route pathname segments</li>\n<li>should not contain <code>index.md</code></li>\n<li>can be ordered with numeric prefixes: <code>(2. Category)</code></li>\n</ul>\n<p>Groupers are useful for visually grouping related pages without adding extra URL segments.</p>\n<p>Example:</p>\n<pre class=\"language-text\"><code class=\"language-text\">docs/\n (Guides)/\n setup.md\n usage.md\n</code></pre>\n<p>Routes:</p>\n<ul>\n<li><code>/setup</code></li>\n<li><code>/usage</code></li>\n</ul>\n<p>Sidebar:</p>\n<pre class=\"language-text\"><code class=\"language-text\">Guides ← grouper label (not a link)\n Setup\n Usage\n</code></pre>\n<h2>Grouper ordering and index collision rules</h2>\n<p>Numeric prefixes on groupers only control ordering among other groupers — they never collide with indexes on regular files or directories. This is because the sort algorithm always places groupers after every regular file and directory at the same level, regardless of what prefix you give them.</p>\n<p>Similarly, numeric prefixes on regular files and directories only control ordering among their own kind.</p>\n<p>In short:</p>\n<ul>\n<li><code>index.md</code> is always sorted first.</li>\n<li>Regular files and directories are sorted next (by label).</li>\n<li>Groupers are sorted last (by label), after all regular files and directories.</li>\n<li>Within each group (regulars and groupers), ordering is controlled by numeric prefixes and <code>localeCompare</code>.</li>\n</ul>\n<p>Example:</p>\n<pre class=\"language-text\"><code class=\"language-text\">docs/\n index.md\n 1. Getting Started.md\n 2. CLI Reference.md\n (1. Guide)/\n routing.md\n (2. Configuration)/\n smm-config.md\n (3. Examples)/\n structure.md\n</code></pre>\n<p>Sidebar order:</p>\n<pre class=\"language-text\"><code class=\"language-text\">Home ← index.md first\nGetting Started\nCLI Reference\nGuide ← grouper label (after all regular files)\n Routing\nConfiguration ← next grouper\n SMM Config\nExamples ← last grouper\n Structure\n</code></pre>\n<h2>Regular directories (without parentheses)</h2>\n<ul>\n<li>appear as collapsible sidebar containers</li>\n<li>can have <code>index.md</code> and be clickable landing pages</li>\n<li>are included in pathname segments of child files</li>\n</ul>\n<p>Example:</p>\n<pre class=\"language-text\"><code class=\"language-text\">docs/\n guides/\n index.md\n setup.md\n</code></pre>\n<p>Routes:</p>\n<ul>\n<li><code>/guides</code></li>\n<li><code>/guides/setup</code></li>\n</ul>\n<h2>Ordered filenames with index prefixes</h2>\n<p>If you use names like:</p>\n<ul>\n<li><code>1. blahblah.md</code></li>\n<li><code>2. blhalbhablah.md</code></li>\n</ul>\n<p>and set <code>trimIndexFromPath: true</code> in config, names can be ordered while emitted as clean paths.</p>\n<p>The index prefix in filenames does not conflict with grouper indexes — they operate in separate sort tiers.</p>\n<h2>Directories vs groupers summary</h2>\n<table>\n<thead>\n<tr>\n<th></th>\n<th>Sidebar rendering</th>\n<th>In URL path</th>\n<th>Can have <code>index.md</code></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Regular directory</td>\n<td>Collapsible</td>\n<td>Yes</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Grouper <code>(Name)</code></td>\n<td>Labeled section</td>\n<td>No</td>\n<td>No</td>\n</tr>\n</tbody>\n</table>\n<h2>Slug generation rules</h2>\n<p>Route path segments are normalized by the CLI:</p>\n<ul>\n<li>converted to lowercase</li>\n<li>spaces/underscores become <code>-</code></li>\n<li>punctuation like <code>.,;&quot;'\\\\:&lt;&gt;</code>?!` is removed</li>\n<li>grouper directory names like <code>(Group)</code> are excluded from final pathname</li>\n</ul>\n"},{"path":"/markdown-and-rendering","content":"<h1>Markdown and Rendering</h1>\n<p>The CLI uses <code>markdown-it</code> and includes:</p>\n<ul>\n<li>footnotes support</li>\n<li>task lists support</li>\n</ul>\n<p>Code highlighting is enabled through Prism with language classes like <code>language-js</code>.</p>\n<p>Useful notes:</p>\n<ul>\n<li><code>linkify</code> is enabled by default in config options.</li>\n<li><code>fuzzyEmail</code> linkification is disabled.</li>\n<li>You can override markdown-it behavior via <code>markdownItOptions</code> in <code>smm.config.json</code>.</li>\n</ul>\n<p>Additional rendering behavior from the web app:</p>\n<ul>\n<li>Heading elements are assigned generated ids for anchor navigation.</li>\n<li>Other extracted elements can receive internal labels for in-page search scroll targets.</li>\n</ul>\n"},{"path":"/build-output-and-assets","content":"<h1>Build Output and Assets</h1>\n<h2>Static site generation (SSG)</h2>\n<p>The CLI generates a fully static site. Every route gets its own <code>.html</code> file with pre-rendered markdown content baked into the DOM. The site works without JavaScript — search engines see all content, and the page is immediately readable.</p>\n<p>Once the JS bundle loads, the React SPA hydrates and takes over navigation for seamless client-side transitions.</p>\n<h2>Build flow</h2>\n<ol>\n<li>Markdown files are scanned and parsed into route/content JSON.</li>\n<li>Generated route data is written under <code>web/src/.generated/</code>.</li>\n<li>Vite builds the web app (CSS + JS bundles).</li>\n<li>Static HTML pages are generated for each route via <code>buildDistRoutesFromRouteTree</code>.</li>\n<li>The built <code>dist/</code> directory is copied to the target docs directory.</li>\n</ol>\n<h2>Generated files</h2>\n<table>\n<thead>\n<tr>\n<th>File</th>\n<th>Purpose</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>.generated/output.json</code></td>\n<td>Route metadata and parsed markdown content for all pages</td>\n</tr>\n<tr>\n<td><code>.generated/paths.json</code></td>\n<td>Nested route tree used to render sidebar groups and collapsibles</td>\n</tr>\n</tbody>\n</table>\n<h2>Public assets</h2>\n<p>If <code>publicPath</code> is configured in <code>smm.config.json</code> and the directory exists, its contents are copied into the web app's <code>public/</code> directory before the Vite build. This is useful for images, fonts, or other static files.</p>\n<h2>Output structure</h2>\n<pre class=\"language-text\"><code class=\"language-text\">dist/\n index.html ← home page (pre-rendered)\n getting-started.html ← each route gets its own .html\n cli-reference.html\n smm-config/\n index.html\n defaults-and-options.html\n trim-and-ordering.html\n assets/\n index-abc123.css ← Vite-built CSS\n index-abc123.js ← Vite-built JS (hydration)\n</code></pre>\n<h2>Defaults</h2>\n<p>If no <code>smm.config.json</code> or <code>.smmignore</code> exists, built-in defaults are used automatically.</p>\n"},{"path":"/smm-config","content":"<h1>smm.config.json</h1>\n<p>Place <code>smm.config.json</code> at docs root.</p>\n<p>Defaults are merged with your overrides.</p>\n<p>Default values come from the CLI's built-in config at <code>cli/src/smm.config.json</code>.</p>\n<p>This is the complete schema:</p>\n<pre class=\"language-typescript\"><code class=\"language-typescript\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">interface</span> <span class=\"token class-name\">SmmConfig</span> <span class=\"token punctuation\">{</span>\n rootTitle<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n description<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n markdownItOptions<span class=\"token operator\">?</span><span class=\"token operator\">:</span> Record<span class=\"token operator\">&lt;</span><span class=\"token builtin\">string</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">any</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span>\n baseRoute<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n outDir<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n publicPath<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n defaultTheme<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n favicon<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n logo<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n name<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n showNameWithLogo<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">boolean</span><span class=\"token punctuation\">;</span>\n og<span class=\"token operator\">?</span><span class=\"token operator\">:</span> OpenGraph<span class=\"token punctuation\">;</span>\n sortRoutes<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">boolean</span><span class=\"token punctuation\">;</span>\n trimIndexFromPath<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">boolean</span><span class=\"token punctuation\">;</span>\n version<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n fonts<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n title<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n name<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n url<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n body<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n name<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n url<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n mono<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n name<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n url<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p>Read next:</p>\n<ul>\n<li><a href=\"/smm-config/defaults-and-options\">Defaults and Options</a></li>\n<li><a href=\"/smm-config/trim-and-ordering\">Trim and Ordering</a></li>\n<li><a href=\"/smm-config/opengraph\">OpenGraph</a></li>\n</ul>\n"},{"path":"/smm-config/defaults-and-options","content":"<h1>Defaults and Options</h1>\n<p><code>smm.config.json</code> supports these useful options:</p>\n<ul>\n<li><code>rootTitle</code>: document title.</li>\n<li><code>description</code>: default description.</li>\n<li><code>markdownItOptions</code>: markdown-it constructor options.</li>\n<li><code>baseRoute</code>: route base prefix.</li>\n<li><code>outDir</code>: output directory name for built artefacts (default <code>&quot;dist&quot;</code>).</li>\n<li><code>publicPath</code>: directory to copy as public assets.</li>\n<li><code>defaultTheme</code>: initial theme.</li>\n<li><code>favicon</code>: favicon URL/path.</li>\n<li><code>logo</code>: logo URL/path.</li>\n<li><code>name</code>: brand/app name.</li>\n<li><code>showNameWithLogo</code>: show name near logo.</li>\n<li><code>og</code>: Open Graph tags object.</li>\n<li><code>sortRoutes</code>: sort routes tree.</li>\n<li><code>trimIndexFromPath</code>: trims filename numeric prefixes from route names.</li>\n<li><code>version</code>: docs/site version string.</li>\n<li><code>fonts</code>: title/body/mono font names and optional stylesheet URLs.</li>\n</ul>\n<h2>Default values used when user config is missing</h2>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"rootTitle\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Serve My MD\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"description\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"A simple markdown to static site builder.\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"baseRoute\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"defaultTheme\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"dark\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"markdownItOptions\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"html\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"xhtmlOut\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"breaks\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"langPrefix\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"language-\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"linkify\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"typographer\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"outDir\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"dist\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"favicon\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"logo\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Serve My MD\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"showNameWithLogo\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"sortRoutes\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"trimIndexFromPath\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p>Example:</p>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"rootTitle\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"My Docs\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"description\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Team documentation\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"baseRoute\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"defaultTheme\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"dark\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"sortRoutes\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"trimIndexFromPath\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"publicPath\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"public\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"outDir\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"my-site\"</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n"},{"path":"/smm-config/trim-and-ordering","content":"<h1>Trim and Ordering</h1>\n<p>Use numbered file names to force custom ordering:</p>\n<ul>\n<li><code>1. intro.md</code></li>\n<li><code>2. install.md</code></li>\n</ul>\n<p>When <code>trimIndexFromPath</code> is <code>true</code>, the numeric prefixes are removed from emitted route names while order stays controlled by your naming.</p>\n<p>Input files:</p>\n<pre class=\"language-text\"><code class=\"language-text\">1. blahblah.md\n2. blhalbhablah.md\n</code></pre>\n<p>Emitted routes:</p>\n<ul>\n<li><code>/blahblah</code></li>\n<li><code>/blhalbhablah</code></li>\n</ul>\n<p>If <code>trimIndexFromPath</code> is <code>false</code>, or not present, then the emitted routes would be:</p>\n<ul>\n<li><code>/1-blahblah</code></li>\n<li><code>/2-blhalbhablah</code></li>\n</ul>\n<p>If route sorting is enabled, routes are sorted lexicographically, with grouped <code>(Name)</code> directories ordered after regular names at the same level. Indexing can also be used for Grouper directories(directories whose names are enclosed within parenthesis) to determine their order.</p>\n"},{"path":"/smm-config/opengraph","content":"<h1>OpenGraph</h1>\n<p>The <code>og</code> field in <code>smm.config.json</code> controls Open Graph meta tags in the generated HTML. These tags control how your site appears when shared on social platforms (Twitter, Discord, Telegram, etc.) and in search results.</p>\n<h2>Schema</h2>\n<pre class=\"language-typescript\"><code class=\"language-typescript\"><span class=\"token keyword\">interface</span> <span class=\"token class-name\">OpenGraph</span> <span class=\"token punctuation\">{</span>\n title<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n type<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n url<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n description<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n site_name<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n determiner<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token string\">\"a\"</span> <span class=\"token operator\">|</span> <span class=\"token string\">\"an\"</span> <span class=\"token operator\">|</span> <span class=\"token string\">\"the\"</span> <span class=\"token operator\">|</span> <span class=\"token string\">\"auto\"</span> <span class=\"token operator\">|</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n locale<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"locale:alternate\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n images<span class=\"token operator\">?</span><span class=\"token operator\">:</span> OpenGraphImage<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n videos<span class=\"token operator\">?</span><span class=\"token operator\">:</span> OpenGraphVideo<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n audios<span class=\"token operator\">?</span><span class=\"token operator\">:</span> OpenGraphAudio<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">interface</span> <span class=\"token class-name\">OpenGraphImage</span> <span class=\"token punctuation\">{</span>\n image<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"image:secure_url\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"image:type\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"image:width\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"image:height\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"image:alt\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">interface</span> <span class=\"token class-name\">OpenGraphVideo</span> <span class=\"token punctuation\">{</span>\n video<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"video:secure_url\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"video:type\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"video:width\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"video:height\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">interface</span> <span class=\"token class-name\">OpenGraphAudio</span> <span class=\"token punctuation\">{</span>\n audio<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"audio:secure_url\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n <span class=\"token string\">\"audio:type\"</span><span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<h2>Basic usage</h2>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"og\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"title\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"My Docs\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"description\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Documentation for my project.\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"website\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"site_name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"My Docs\"</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p>This generates:</p>\n<pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>og:title<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>My Docs<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>og:description<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Documentation for my project.<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>og:type<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>website<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>og:site_name<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>My Docs<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n</code></pre>\n<h2>With images</h2>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"og\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"title\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"My Docs\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"description\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Documentation for my project.\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"images\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"image\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://example.com/og-image.png\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"image:width\"</span><span class=\"token operator\">:</span> <span class=\"token number\">1200</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"image:height\"</span><span class=\"token operator\">:</span> <span class=\"token number\">630</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"image:alt\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"My Docs preview\"</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">]</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<h2>With videos and audio</h2>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"og\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"title\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Video Docs\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"videos\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"video\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://example.com/trailer.mp4\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"video:type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"video/mp4\"</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"audios\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n <span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"audio\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://example.com/song.mp3\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"audio:type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"audio/mpeg\"</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">]</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<h2>Locale</h2>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"og\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"locale\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"en_US\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"locale:alternate\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"fr_FR\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"es_ES\"</span><span class=\"token punctuation\">]</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<h2>How it works</h2>\n<p>The CLI reads the <code>og</code> field from <code>smm.config.json</code> and renders each entry as <code>&lt;meta property=&quot;og:key&quot; content=&quot;value&quot;&gt;</code> tags in the HTML <code>&lt;head&gt;</code>. Arrays (like <code>locale:alternate</code>) produce one meta tag per value. Image, video, and audio objects render their properties as flat <code>og:*</code> meta tags.</p>\n"},{"path":"/smm-ignore","content":"<h1>.smmignore</h1>\n<p>Create <code>.smmignore</code> at docs root to skip paths during markdown traversal.</p>\n<p>Rules are glob-like, processed top-to-bottom.</p>\n<ul>\n<li>Lines starting with <code>#</code> are comments.</li>\n<li>Empty lines are ignored.</li>\n<li>Prefix with <code>!</code> to un-ignore.</li>\n</ul>\n<p>Example:</p>\n<pre class=\"language-text\"><code class=\"language-text\">drafts/**\nprivate/**\n!private/keep.md\n</code></pre>\n<p>Paths are evaluated against traversal targets in the docs tree; ignored paths are skipped during route/content generation.</p>\n"},{"path":"/structure-examples","content":"<h1>Structure Examples</h1>\n<h2>Group directory (not in pathname)</h2>\n<pre class=\"language-text\"><code class=\"language-text\">docs/\n (Category)/\n tos.md\n</code></pre>\n<p>Route: <code>/tos</code></p>\n<h2>Normal directory with landing page</h2>\n<pre class=\"language-text\"><code class=\"language-text\">docs/\n features/\n index.md\n tea.md\n</code></pre>\n<p>Routes:</p>\n<ul>\n<li><code>/features</code></li>\n<li><code>/features/tea</code></li>\n</ul>\n<h2>Root landing page</h2>\n<pre class=\"language-text\"><code class=\"language-text\">docs/\n index.md\n about.md\n</code></pre>\n<p>Routes:</p>\n<ul>\n<li><code>/</code></li>\n<li><code>/about</code></li>\n</ul>\n"},{"path":"/config-examples","content":"<h1>Config Examples</h1>\n<h2>Basic customization</h2>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"rootTitle\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Company Docs\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"description\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Internal knowledge base\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"defaultTheme\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"dark\"</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"sortRoutes\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<h2>Ordered file naming + trimmed paths</h2>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"sortRoutes\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n <span class=\"token property\">\"trimIndexFromPath\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<h2>Public assets</h2>\n<pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n <span class=\"token property\">\"publicPath\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"public\"</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p>This copies <code>public</code> from docs root into build public assets, also ignores it for routes building.</p>\n"}],"outDir":"docs","fonts":{"title":"Exo","body":"Commissioner","mono":"Fira Code"}}
@@ -1 +1 @@
1
- [{"label":"","children":null,"pathSegment":""},{"label":"features","children":[{"label":"","children":null,"pathSegment":""},{"label":"choorma","children":null,"pathSegment":"choorma"},{"label":"coffee","children":null,"pathSegment":"coffee"},{"label":"ghee-dudh","children":null,"pathSegment":"ghee-dudh"},{"label":"tea","children":null,"pathSegment":"tea"}],"pathSegment":"features","isGrouper":false},{"label":"muah","children":null,"pathSegment":"muah"},{"label":"Category","children":[{"label":"zaram Chand","children":null,"pathSegment":"zaram-chand"},{"label":"tos","children":null,"pathSegment":"tos"}],"pathSegment":"","isGrouper":true}]
1
+ [{"label":"","children":null,"pathSegment":""},{"label":"Getting Started","children":null,"pathSegment":"getting-started"},{"label":"CLI Reference","children":null,"pathSegment":"cli-reference"},{"label":"Key Behaviors","children":null,"pathSegment":"key-behaviors"},{"label":"Why serve-my-md","children":null,"pathSegment":"why-serve-my-md"},{"label":"Guide","children":[{"label":"Routing and Sidebar Patterns","children":null,"pathSegment":"routing-and-sidebar-patterns"},{"label":"Markdown and Rendering","children":null,"pathSegment":"markdown-and-rendering"},{"label":"Build Output and Assets","children":null,"pathSegment":"build-output-and-assets"}],"pathSegment":"","isGrouper":true},{"label":"Configuration","children":[{"label":"SMM Config","children":[{"label":"","children":null,"pathSegment":""},{"label":"Defaults and Options","children":null,"pathSegment":"defaults-and-options"},{"label":"Trim and Ordering","children":null,"pathSegment":"trim-and-ordering"},{"label":"OpenGraph","children":null,"pathSegment":"opengraph"}],"pathSegment":"smm-config","isGrouper":false},{"label":"SMM Ignore","children":null,"pathSegment":"smm-ignore","isGrouper":false}],"pathSegment":"","isGrouper":true},{"label":"Examples","children":[{"label":"Structure Examples","children":null,"pathSegment":"structure-examples"},{"label":"Config Examples","children":null,"pathSegment":"config-examples"}],"pathSegment":"","isGrouper":true}]
@@ -57,17 +57,18 @@ export default function Rendrer({
57
57
 
58
58
  const article = articleRef.current;
59
59
  article.querySelectorAll('a').forEach((elem: HTMLAnchorElement) => {
60
+ if (
61
+ elem.getAttribute('href')?.startsWith('http://') ||
62
+ elem.getAttribute('href')?.startsWith('https://')
63
+ )
64
+ return;
65
+
60
66
  elem.setAttribute(
61
67
  'href',
62
68
  pathBrowser.join(out.baseRoute || '/', elem.getAttribute('href') || '')
63
69
  );
64
70
 
65
71
  elem.addEventListener('click', (e) => {
66
- if (
67
- elem.getAttribute('href')?.startsWith('http://') ||
68
- elem.getAttribute('href')?.startsWith('https://')
69
- )
70
- return;
71
72
  e.preventDefault();
72
73
  navigate({ to: elem.getAttribute('href') || '/' });
73
74
  });
Binary file