nrdocs 0.1.6 → 0.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/dist/bin.mjs CHANGED
@@ -815,11 +815,11 @@ async function handleInit(args2) {
815
815
  }
816
816
 
817
817
  // src/commands/publish.ts
818
- import * as fs7 from "node:fs";
818
+ import * as fs8 from "node:fs";
819
819
 
820
820
  // src/renderer/index.ts
821
- import * as fs5 from "node:fs";
822
- import * as path6 from "node:path";
821
+ import * as fs6 from "node:fs";
822
+ import * as path7 from "node:path";
823
823
 
824
824
  // ../../node_modules/.pnpm/markdown-it@14.1.1/node_modules/markdown-it/lib/common/utils.mjs
825
825
  var utils_exports = {};
@@ -6002,6 +6002,21 @@ var md = new lib_default({
6002
6002
  typographer: false
6003
6003
  // No smart quotes or typographic replacements
6004
6004
  });
6005
+ var defaultFence = md.renderer.rules.fence;
6006
+ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
6007
+ const token = tokens[idx];
6008
+ const lang = token.info.trim().split(/\s+/g)[0];
6009
+ if (lang === "mermaid") {
6010
+ const escaped = md.utils.escapeHtml(token.content.trim());
6011
+ return `<pre class="mermaid">${escaped}</pre>
6012
+ `;
6013
+ }
6014
+ return defaultFence(tokens, idx, options, env, self);
6015
+ };
6016
+ var MERMAID_FENCE_RE = /^```mermaid\s*$/m;
6017
+ function contentHasMermaid(content) {
6018
+ return MERMAID_FENCE_RE.test(content);
6019
+ }
6005
6020
  function renderMarkdown(content) {
6006
6021
  return md.render(content);
6007
6022
  }
@@ -6171,11 +6186,39 @@ function addHeadingIds(html) {
6171
6186
  });
6172
6187
  }
6173
6188
  function wrapInTemplate(options) {
6174
- const { title, siteTitle, content, nav, canonicalUrl, baseUrl } = options;
6189
+ const {
6190
+ title,
6191
+ siteTitle,
6192
+ content,
6193
+ nav,
6194
+ canonicalUrl,
6195
+ baseUrl,
6196
+ includeMermaid = false,
6197
+ mermaidScriptSrc = null
6198
+ } = options;
6175
6199
  const pageTitle = title === siteTitle ? siteTitle : `${title} - ${siteTitle}`;
6176
6200
  const contentWithIds = addHeadingIds(content);
6177
6201
  const toc = extractToc(contentWithIds);
6178
6202
  const hasToc = toc.length > 1;
6203
+ const mermaidBlock = includeMermaid && mermaidScriptSrc ? `<script src="${escapeHtml2(mermaidScriptSrc)}" defer></script>
6204
+ <script>
6205
+ (function(){
6206
+ function theme(){var t=document.documentElement.dataset.theme;return t==='dark'||t==='light'?t:(window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light');}
6207
+ function api(){
6208
+ var g=typeof globalThis!=='undefined'?globalThis:(typeof window!=='undefined'?window:null);
6209
+ if(!g||!g.mermaid)return null;
6210
+ var m=g.mermaid;
6211
+ return (m.default&&typeof m.default.initialize==='function')?m.default:m;
6212
+ }
6213
+ function initMermaid(){
6214
+ var m=api();if(!m)return;
6215
+ m.initialize({startOnLoad:true,theme:theme()==='dark'?'dark':'default'});
6216
+ m.run();
6217
+ }
6218
+ document.addEventListener('DOMContentLoaded',initMermaid);
6219
+ document.addEventListener('nrdocs-theme-change',initMermaid);
6220
+ })();
6221
+ </script>` : "";
6179
6222
  return `<!DOCTYPE html>
6180
6223
  <html lang="en">
6181
6224
  <head>
@@ -6187,48 +6230,97 @@ function wrapInTemplate(options) {
6187
6230
  <meta name="generator" content="nrdocs">
6188
6231
  <title>${escapeHtml2(pageTitle)}</title>
6189
6232
  <link rel="canonical" href="${escapeHtml2(canonicalUrl)}">
6233
+ <script>
6234
+ (function(){try{var s=localStorage.getItem('nrdocs-theme');if(s==='light'||s==='dark')document.documentElement.dataset.theme=s;}catch(e){}})();
6235
+ </script>
6190
6236
  <style>
6237
+ :root{
6238
+ --text:#1a1a1a;--text-muted:#555;--text-footer:#888;
6239
+ --bg-body:#fff;--bg-sidebar:#fafafa;--bg-hover:#e8e8e8;--bg-active:#e0e7ff;
6240
+ --border:#e0e0e0;--border-light:#e8e8e8;
6241
+ --link:#1d4ed8;--link-active:#1d4ed8;
6242
+ --code-bg:#f3f4f6;--pre-bg:#1e1e1e;--pre-text:#d4d4d4;
6243
+ --th-bg:#f5f5f5;--blockquote:#555;
6244
+ --toc-title:#666;--toc-link:#555;
6245
+ }
6246
+ @media(prefers-color-scheme:dark){
6247
+ html:not([data-theme]){
6248
+ --text:#e5e5e5;--text-muted:#a3a3a3;--text-footer:#737373;
6249
+ --bg-body:#0a0a0a;--bg-sidebar:#111;--bg-hover:#262626;--bg-active:#1e3a5f;
6250
+ --border:#333;--border-light:#262626;
6251
+ --link:#60a5fa;--link-active:#93c5fd;
6252
+ --code-bg:#262626;--pre-bg:#1a1a1a;--pre-text:#d4d4d4;
6253
+ --th-bg:#1a1a1a;--blockquote:#a3a3a3;
6254
+ --toc-title:#a3a3a3;--toc-link:#a3a3a3;
6255
+ }
6256
+ }
6257
+ html[data-theme="dark"]{
6258
+ --text:#e5e5e5;--text-muted:#a3a3a3;--text-footer:#737373;
6259
+ --bg-body:#0a0a0a;--bg-sidebar:#111;--bg-hover:#262626;--bg-active:#1e3a5f;
6260
+ --border:#333;--border-light:#262626;
6261
+ --link:#60a5fa;--link-active:#93c5fd;
6262
+ --code-bg:#262626;--pre-bg:#1a1a1a;--pre-text:#d4d4d4;
6263
+ --th-bg:#1a1a1a;--blockquote:#a3a3a3;
6264
+ --toc-title:#a3a3a3;--toc-link:#a3a3a3;
6265
+ }
6266
+ html[data-theme="light"]{
6267
+ --text:#1a1a1a;--text-muted:#555;--text-footer:#888;
6268
+ --bg-body:#fff;--bg-sidebar:#fafafa;--bg-hover:#e8e8e8;--bg-active:#e0e7ff;
6269
+ --border:#e0e0e0;--border-light:#e8e8e8;
6270
+ --link:#1d4ed8;--link-active:#1d4ed8;
6271
+ --code-bg:#f3f4f6;--pre-bg:#1e1e1e;--pre-text:#d4d4d4;
6272
+ --th-bg:#f5f5f5;--blockquote:#555;
6273
+ --toc-title:#666;--toc-link:#555;
6274
+ }
6191
6275
  *{margin:0;padding:0;box-sizing:border-box}
6192
- body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:1.0625rem;line-height:1.7;color:#1a1a1a;display:flex;min-height:100vh}
6193
- nav.sidebar{width:260px;padding:1.5rem;border-right:1px solid #e0e0e0;background:#fafafa;overflow-y:auto;flex-shrink:0;position:sticky;top:0;height:100vh}
6194
- nav.sidebar .site-title{font-weight:700;font-size:1.1rem;margin-bottom:1rem;color:#111}
6276
+ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:1.0625rem;line-height:1.7;color:var(--text);background:var(--bg-body);display:flex;min-height:100vh}
6277
+ nav.sidebar{width:260px;padding:1.5rem;border-right:1px solid var(--border);background:var(--bg-sidebar);overflow-y:auto;flex-shrink:0;position:sticky;top:0;height:100vh}
6278
+ .site-header{display:flex;align-items:center;justify-content:space-between;gap:0.5rem;margin-bottom:1rem}
6279
+ nav.sidebar .site-title{font-weight:700;font-size:1.1rem;color:var(--text);flex:1;min-width:0}
6280
+ #theme-toggle{background:var(--bg-hover);border:1px solid var(--border);border-radius:6px;padding:0.35rem 0.5rem;cursor:pointer;font-size:1rem;line-height:1;color:var(--text);flex-shrink:0}
6281
+ #theme-toggle:hover{background:var(--bg-active)}
6195
6282
  nav.sidebar ul{list-style:none}
6196
6283
  nav.sidebar li{margin-bottom:0.25rem}
6197
- nav.sidebar a{color:#333;text-decoration:none;padding:0.3rem 0.6rem;display:block;border-radius:4px;font-size:0.95rem}
6198
- nav.sidebar a:hover{background:#e8e8e8}
6199
- nav.sidebar a.active{background:#e0e7ff;color:#1d4ed8;font-weight:500}
6284
+ nav.sidebar a{color:var(--text-muted);text-decoration:none;padding:0.3rem 0.6rem;display:block;border-radius:4px;font-size:0.95rem}
6285
+ nav.sidebar a:hover{background:var(--bg-hover);color:var(--text)}
6286
+ nav.sidebar a.active{background:var(--bg-active);color:var(--link-active);font-weight:500}
6200
6287
  .content-wrapper{flex:1;display:flex;min-width:0}
6201
6288
  main{flex:1;padding:2.5rem 3rem;max-width:52rem;min-width:0;overflow-wrap:break-word}
6202
- main h1{font-size:2.2rem;margin-bottom:1.2rem;border-bottom:1px solid #e0e0e0;padding-bottom:0.5rem;line-height:1.3}
6203
- main h2{font-size:1.6rem;margin-top:2.5rem;margin-bottom:0.75rem;line-height:1.3}
6204
- main h3{font-size:1.3rem;margin-top:1.8rem;margin-bottom:0.5rem;line-height:1.4}
6289
+ main h1{font-size:2.2rem;margin-bottom:1.2rem;border-bottom:1px solid var(--border);padding-bottom:0.5rem;line-height:1.3;color:var(--text)}
6290
+ main h2{font-size:1.6rem;margin-top:2.5rem;margin-bottom:0.75rem;line-height:1.3;color:var(--text)}
6291
+ main h3{font-size:1.3rem;margin-top:1.8rem;margin-bottom:0.5rem;line-height:1.4;color:var(--text)}
6205
6292
  main p{margin-bottom:1.1rem}
6206
- main a{color:#1d4ed8;text-decoration:underline}
6207
- main code{background:#f3f4f6;padding:0.2rem 0.4rem;border-radius:3px;font-size:0.88em}
6208
- main pre{background:#1e1e1e;color:#d4d4d4;padding:1.2rem;border-radius:6px;overflow-x:auto;margin-bottom:1.2rem;font-size:0.9rem;line-height:1.5}
6293
+ main a{color:var(--link);text-decoration:underline}
6294
+ main code{background:var(--code-bg);padding:0.2rem 0.4rem;border-radius:3px;font-size:0.88em;color:var(--text)}
6295
+ main pre{background:var(--pre-bg);color:var(--pre-text);padding:1.2rem;border-radius:6px;overflow-x:auto;margin-bottom:1.2rem;font-size:0.9rem;line-height:1.5}
6209
6296
  main pre code{background:none;padding:0;color:inherit;font-size:inherit}
6297
+ main pre.mermaid{background:transparent;color:var(--text);padding:0;margin:1.5rem 0;overflow-x:auto}
6210
6298
  main table{border-collapse:collapse;width:100%;margin-bottom:1.2rem}
6211
- main th,main td{border:1px solid #d0d0d0;padding:0.6rem 0.85rem;text-align:left}
6212
- main th{background:#f5f5f5;font-weight:600}
6299
+ main th,main td{border:1px solid var(--border);padding:0.6rem 0.85rem;text-align:left;color:var(--text)}
6300
+ main th{background:var(--th-bg);font-weight:600}
6213
6301
  main img{max-width:100%;height:auto;border-radius:4px}
6214
- main blockquote{border-left:4px solid #d0d0d0;padding-left:1rem;margin-bottom:1.1rem;color:#555;font-style:italic}
6302
+ main blockquote{border-left:4px solid var(--border);padding-left:1rem;margin-bottom:1.1rem;color:var(--blockquote);font-style:italic}
6215
6303
  main ul,main ol{margin-bottom:1.1rem;padding-left:1.5rem}
6216
6304
  main li{margin-bottom:0.3rem}
6217
- aside.toc{width:220px;padding:1.5rem 1rem;position:sticky;top:0;height:100vh;overflow-y:auto;flex-shrink:0;border-left:1px solid #e8e8e8}
6218
- aside.toc .toc-title{font-size:0.8rem;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#666;margin-bottom:0.75rem}
6305
+ aside.toc{width:220px;padding:1.5rem 1rem;position:sticky;top:0;height:100vh;overflow-y:auto;flex-shrink:0;border-left:1px solid var(--border-light);background:var(--bg-body)}
6306
+ aside.toc .toc-title{font-size:0.8rem;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:var(--toc-title);margin-bottom:0.75rem}
6219
6307
  aside.toc ul{list-style:none}
6220
6308
  aside.toc li{margin-bottom:0.3rem}
6221
- aside.toc a{color:#555;text-decoration:none;font-size:0.85rem;display:block;padding:0.15rem 0;border-radius:2px}
6222
- aside.toc a:hover{color:#1d4ed8}
6309
+ aside.toc a{color:var(--toc-link);text-decoration:none;font-size:0.85rem;display:block;padding:0.15rem 0;border-radius:2px}
6310
+ aside.toc a:hover{color:var(--link)}
6223
6311
  aside.toc .toc-h3{padding-left:0.75rem}
6224
- footer{padding:1.5rem 3rem;border-top:1px solid #e8e8e8;color:#888;font-size:0.8rem;text-align:center}
6312
+ footer{padding:1.5rem 0;border-top:1px solid var(--border-light);color:var(--text-footer);font-size:0.8rem;text-align:center;margin-top:2rem}
6313
+ footer a{color:var(--link)}
6225
6314
  @media(max-width:1100px){aside.toc{display:none}}
6226
- @media(max-width:768px){body{flex-direction:column}nav.sidebar{width:100%;border-right:none;border-bottom:1px solid #e0e0e0;position:static;height:auto}main{padding:1.5rem}}
6315
+ @media(max-width:768px){body{flex-direction:column}nav.sidebar{width:100%;border-right:none;border-bottom:1px solid var(--border);position:static;height:auto}main{padding:1.5rem}}
6227
6316
  </style>
6228
6317
  </head>
6229
6318
  <body>
6230
6319
  <nav class="sidebar">
6320
+ <div class="site-header">
6231
6321
  <div class="site-title">${escapeHtml2(siteTitle)}</div>
6322
+ <button type="button" id="theme-toggle" aria-label="Toggle color theme" title="Toggle light/dark mode">&#9789;</button>
6323
+ </div>
6232
6324
  <ul>
6233
6325
  ${renderNavItems(nav, baseUrl)}
6234
6326
  </ul>
@@ -6240,6 +6332,32 @@ ${contentWithIds}
6240
6332
  </main>
6241
6333
  ${hasToc ? renderToc(toc) : ""}
6242
6334
  </div>
6335
+ <script>
6336
+ (function(){
6337
+ var key='nrdocs-theme';
6338
+ var root=document.documentElement;
6339
+ function resolved(){
6340
+ var t=root.dataset.theme;
6341
+ if(t==='dark'||t==='light')return t;
6342
+ return window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';
6343
+ }
6344
+ function apply(next){
6345
+ root.dataset.theme=next;
6346
+ try{localStorage.setItem(key,next);}catch(e){}
6347
+ document.dispatchEvent(new CustomEvent('nrdocs-theme-change',{detail:{theme:next}}));
6348
+ var btn=document.getElementById('theme-toggle');
6349
+ if(btn)btn.textContent=next==='dark'?'\\u2600':'\\u263E';
6350
+ }
6351
+ var btn=document.getElementById('theme-toggle');
6352
+ if(btn){
6353
+ btn.textContent=resolved()==='dark'?'\\u2600':'\\u263E';
6354
+ btn.addEventListener('click',function(){
6355
+ apply(resolved()==='dark'?'light':'dark');
6356
+ });
6357
+ }
6358
+ })();
6359
+ </script>
6360
+ ${mermaidBlock}
6243
6361
  </body>
6244
6362
  </html>`;
6245
6363
  }
@@ -6306,6 +6424,35 @@ function collectFromDir(dir, rootDir, results) {
6306
6424
  }
6307
6425
  }
6308
6426
 
6427
+ // src/renderer/mermaid-runtime.ts
6428
+ import * as fs5 from "node:fs";
6429
+ import * as path6 from "node:path";
6430
+ import { fileURLToPath } from "node:url";
6431
+ var __dirname = path6.dirname(fileURLToPath(import.meta.url));
6432
+ var MERMAID_RUNTIME_REL = "runtime/mermaid.min.js";
6433
+ var MERMAID_ARTIFACT_PATH = "_nrdocs/mermaid.min.js";
6434
+ function mermaidRuntimeCandidates() {
6435
+ return [
6436
+ path6.join(__dirname, MERMAID_RUNTIME_REL),
6437
+ path6.join(__dirname, "../../dist/runtime/mermaid.min.js")
6438
+ ];
6439
+ }
6440
+ function loadMermaidRuntime() {
6441
+ for (const candidate of mermaidRuntimeCandidates()) {
6442
+ if (fs5.existsSync(candidate)) {
6443
+ return fs5.readFileSync(candidate);
6444
+ }
6445
+ }
6446
+ throw new Error(
6447
+ "Mermaid runtime not found. Run: pnpm --filter nrdocs bundle (or pnpm bundle in packages/cli)"
6448
+ );
6449
+ }
6450
+ function mermaidScriptSrcForOutput(outputPath) {
6451
+ const depth = outputPath.split("/").length - 1;
6452
+ const prefix = depth > 0 ? "../".repeat(depth) : "";
6453
+ return `${prefix}${MERMAID_ARTIFACT_PATH}`;
6454
+ }
6455
+
6309
6456
  // src/renderer/index.ts
6310
6457
  function resolveNavItems(resolvedDocsDir, nav, indexPath) {
6311
6458
  if (nav && nav !== "auto" && Array.isArray(nav)) {
@@ -6315,15 +6462,18 @@ function resolveNavItems(resolvedDocsDir, nav, indexPath) {
6315
6462
  }
6316
6463
  async function renderSite(options) {
6317
6464
  const { docsDir, siteTitle, baseUrl, owner, repo, nav, indexPath = "index.md" } = options;
6318
- const resolvedDocsDir = path6.resolve(docsDir);
6465
+ const resolvedDocsDir = path7.resolve(docsDir);
6319
6466
  const navItems = resolveNavItems(resolvedDocsDir, nav, indexPath);
6320
6467
  const siteBase = `/${owner}/${repo}/`;
6321
6468
  const renderedFiles = [];
6469
+ let siteHasMermaid = false;
6322
6470
  for (const navItem of navItems) {
6323
- const filePath = path6.join(resolvedDocsDir, navItem.path);
6324
- const markdownContent = fs5.readFileSync(filePath, "utf-8");
6471
+ const filePath = path7.join(resolvedDocsDir, navItem.path);
6472
+ const markdownContent = fs6.readFileSync(filePath, "utf-8");
6473
+ const pageHasMermaid = contentHasMermaid(markdownContent);
6474
+ if (pageHasMermaid) siteHasMermaid = true;
6325
6475
  let html = renderMarkdown(markdownContent);
6326
- const fileDir = path6.dirname(navItem.path);
6476
+ const fileDir = path7.dirname(navItem.path);
6327
6477
  const baseLinkPath = fileDir === "." ? "" : fileDir;
6328
6478
  html = rewriteLinks(html, baseLinkPath, owner, repo);
6329
6479
  const pageTitle = extractTitle(markdownContent, navItem.path);
@@ -6332,20 +6482,28 @@ async function renderSite(options) {
6332
6482
  ...item,
6333
6483
  active: item.path === navItem.path
6334
6484
  }));
6485
+ const outputPath = navItem.href === "" ? "index.html" : navItem.href.replace(/\/$/, "") + "/index.html";
6335
6486
  const fullHtml = wrapInTemplate({
6336
6487
  title: pageTitle,
6337
6488
  siteTitle,
6338
6489
  content: html,
6339
6490
  nav: navWithActive,
6340
6491
  canonicalUrl,
6341
- baseUrl: siteBase
6492
+ baseUrl: siteBase,
6493
+ includeMermaid: pageHasMermaid,
6494
+ mermaidScriptSrc: pageHasMermaid ? mermaidScriptSrcForOutput(outputPath) : null
6342
6495
  });
6343
- const outputPath = navItem.href === "" ? "index.html" : navItem.href.replace(/\/$/, "") + "/index.html";
6344
6496
  renderedFiles.push({
6345
6497
  path: outputPath,
6346
6498
  content: Buffer.from(fullHtml, "utf-8")
6347
6499
  });
6348
6500
  }
6501
+ if (siteHasMermaid) {
6502
+ renderedFiles.push({
6503
+ path: MERMAID_ARTIFACT_PATH,
6504
+ content: loadMermaidRuntime()
6505
+ });
6506
+ }
6349
6507
  const assets = collectAssets(resolvedDocsDir);
6350
6508
  renderedFiles.push(...assets);
6351
6509
  const manifest = {
@@ -6442,8 +6600,8 @@ function normalizeApiBaseUrl(url) {
6442
6600
  }
6443
6601
  function buildApiUrl(baseUrl, apiPath) {
6444
6602
  const { url } = normalizeApiBaseUrl(baseUrl);
6445
- const path11 = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
6446
- return `${url}${path11}`;
6603
+ const path12 = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
6604
+ return `${url}${path12}`;
6447
6605
  }
6448
6606
  function extractFetchError(err) {
6449
6607
  if (!(err instanceof Error)) {
@@ -6691,8 +6849,8 @@ var ApiClient = class {
6691
6849
  }
6692
6850
  };
6693
6851
  }
6694
- async request(method, path11, body, timeoutMs = DEFAULT_TIMEOUT_MS) {
6695
- const url = buildApiUrl(this.baseUrl, path11);
6852
+ async request(method, path12, body, timeoutMs = DEFAULT_TIMEOUT_MS) {
6853
+ const url = buildApiUrl(this.baseUrl, path12);
6696
6854
  const controller = new AbortController();
6697
6855
  const timer = setTimeout(() => controller.abort(), timeoutMs);
6698
6856
  const init = {
@@ -6823,21 +6981,21 @@ var ApiClient = class {
6823
6981
  };
6824
6982
 
6825
6983
  // src/config/docs-config.ts
6826
- import * as fs6 from "node:fs";
6827
- import * as path7 from "node:path";
6984
+ import * as fs7 from "node:fs";
6985
+ import * as path8 from "node:path";
6828
6986
  import YAML from "yaml";
6829
6987
  function loadDocsConfig(docsDir) {
6830
- const configPath = path7.resolve(docsDir, "nrdocs.yml");
6831
- if (!fs6.existsSync(configPath)) {
6988
+ const configPath = path8.resolve(docsDir, "nrdocs.yml");
6989
+ if (!fs7.existsSync(configPath)) {
6832
6990
  throw new Error(`Config file not found: ${configPath}`);
6833
6991
  }
6834
- const raw = fs6.readFileSync(configPath, "utf-8");
6992
+ const raw = fs7.readFileSync(configPath, "utf-8");
6835
6993
  const config2 = YAML.parse(raw);
6836
6994
  if (!config2 || typeof config2 !== "object") {
6837
6995
  throw new Error(`Invalid config: ${configPath}`);
6838
6996
  }
6839
6997
  const sourceDir = config2.content?.source_dir ?? ".";
6840
- const contentDir = path7.resolve(docsDir, sourceDir);
6998
+ const contentDir = path8.resolve(docsDir, sourceDir);
6841
6999
  return { config: config2, configPath, contentDir };
6842
7000
  }
6843
7001
  function hasExplicitNav(config2) {
@@ -6883,8 +7041,8 @@ function validateNavPaths(entries, contentDir) {
6883
7041
  errors.push(`Duplicate nav path: ${p}`);
6884
7042
  }
6885
7043
  seen.add(p);
6886
- const full = path7.join(contentDir, p);
6887
- if (!fs6.existsSync(full)) {
7044
+ const full = path8.join(contentDir, p);
7045
+ if (!fs7.existsSync(full)) {
6888
7046
  errors.push(`Nav path not found: ${p}`);
6889
7047
  }
6890
7048
  if (e.children?.length) walk(e.children);
@@ -6894,7 +7052,7 @@ function validateNavPaths(entries, contentDir) {
6894
7052
  return { valid: errors.length === 0, errors };
6895
7053
  }
6896
7054
  function writeNavToConfig(configPath, navEntries) {
6897
- let raw = fs6.readFileSync(configPath, "utf-8");
7055
+ let raw = fs7.readFileSync(configPath, "utf-8");
6898
7056
  raw = raw.replace(/^# content\.nav generated by: nrdocs nav generate\n/gm, "");
6899
7057
  const config2 = YAML.parse(raw);
6900
7058
  if (!config2 || typeof config2 !== "object") {
@@ -6907,7 +7065,7 @@ function writeNavToConfig(configPath, navEntries) {
6907
7065
  const doc = new YAML.Document(config2);
6908
7066
  const header = "# content.nav generated by: nrdocs nav generate\n";
6909
7067
  const body = doc.toString();
6910
- fs6.writeFileSync(configPath, header + body, "utf-8");
7068
+ fs7.writeFileSync(configPath, header + body, "utf-8");
6911
7069
  }
6912
7070
  function formatNavYaml(navEntries) {
6913
7071
  const partial = {
@@ -6932,10 +7090,10 @@ function parsePublishArgs(args2) {
6932
7090
  return opts;
6933
7091
  }
6934
7092
  function validateConfig2(configPath) {
6935
- if (!fs7.existsSync(configPath)) {
7093
+ if (!fs8.existsSync(configPath)) {
6936
7094
  return { valid: false, error: `Config file not found: ${configPath}` };
6937
7095
  }
6938
- const content = fs7.readFileSync(configPath, "utf-8");
7096
+ const content = fs8.readFileSync(configPath, "utf-8");
6939
7097
  if (!content.includes("site:")) {
6940
7098
  return { valid: false, error: 'Config file missing "site:" section' };
6941
7099
  }
@@ -7115,8 +7273,8 @@ async function handlePublish(args2) {
7115
7273
  }
7116
7274
 
7117
7275
  // src/commands/doctor.ts
7118
- import * as fs8 from "node:fs";
7119
- import * as path8 from "node:path";
7276
+ import * as fs9 from "node:fs";
7277
+ import * as path9 from "node:path";
7120
7278
  function parseDoctorArgs(args2) {
7121
7279
  const opts = {};
7122
7280
  for (const arg of args2) {
@@ -7126,11 +7284,11 @@ function parseDoctorArgs(args2) {
7126
7284
  return opts;
7127
7285
  }
7128
7286
  function countMarkdownFiles(docsDir) {
7129
- if (!fs8.existsSync(docsDir)) return 0;
7287
+ if (!fs9.existsSync(docsDir)) return 0;
7130
7288
  let count = 0;
7131
7289
  const walk = (dir) => {
7132
- for (const entry of fs8.readdirSync(dir, { withFileTypes: true })) {
7133
- const full = path8.join(dir, entry.name);
7290
+ for (const entry of fs9.readdirSync(dir, { withFileTypes: true })) {
7291
+ const full = path9.join(dir, entry.name);
7134
7292
  if (entry.isDirectory()) walk(full);
7135
7293
  else if (entry.name.endsWith(".md")) count++;
7136
7294
  }
@@ -7142,22 +7300,22 @@ async function handleDoctor(args2) {
7142
7300
  const opts = parseDoctorArgs(args2);
7143
7301
  const inCI = opts.ci || process.env["GITHUB_ACTIONS"] === "true";
7144
7302
  const checks = [];
7145
- const isGitRepo = fs8.existsSync(path8.resolve(".git"));
7303
+ const isGitRepo = fs9.existsSync(path9.resolve(".git"));
7146
7304
  checks.push({
7147
7305
  section: "Repo setup",
7148
7306
  name: "Git repository",
7149
7307
  status: isGitRepo ? "ok" : "fail",
7150
7308
  message: isGitRepo ? "Found .git directory" : "Not a git repository"
7151
7309
  });
7152
- const configPath = path8.resolve("docs", "nrdocs.yml");
7153
- const hasConfig = fs8.existsSync(configPath);
7310
+ const configPath = path9.resolve("docs", "nrdocs.yml");
7311
+ const hasConfig = fs9.existsSync(configPath);
7154
7312
  checks.push({
7155
7313
  section: "Repo setup",
7156
7314
  name: "Docs config",
7157
7315
  status: hasConfig ? "ok" : "fail",
7158
7316
  message: hasConfig ? "Found docs/nrdocs.yml" : "Missing docs/nrdocs.yml \u2014 run: nrdocs init"
7159
7317
  });
7160
- const docsDir = path8.resolve("docs");
7318
+ const docsDir = path9.resolve("docs");
7161
7319
  const mdCount = countMarkdownFiles(docsDir);
7162
7320
  checks.push({
7163
7321
  section: "Repo setup",
@@ -7165,8 +7323,8 @@ async function handleDoctor(args2) {
7165
7323
  status: mdCount > 0 ? "ok" : "warn",
7166
7324
  message: mdCount > 0 ? `${mdCount} markdown file(s) in docs/` : "No .md files in docs/ \u2014 publish will produce an empty site"
7167
7325
  });
7168
- const workflowPath = path8.resolve(".github", "workflows", "nrdocs.yml");
7169
- const hasWorkflow = fs8.existsSync(workflowPath);
7326
+ const workflowPath = path9.resolve(".github", "workflows", "nrdocs.yml");
7327
+ const hasWorkflow = fs9.existsSync(workflowPath);
7170
7328
  checks.push({
7171
7329
  section: "Repo setup",
7172
7330
  name: "GitHub workflow",
@@ -7176,7 +7334,7 @@ async function handleDoctor(args2) {
7176
7334
  let configApiUrl;
7177
7335
  let workflowApiUrl;
7178
7336
  if (hasConfig) {
7179
- const content = fs8.readFileSync(configPath, "utf-8");
7337
+ const content = fs9.readFileSync(configPath, "utf-8");
7180
7338
  configApiUrl = parseApiUrlFromConfig(content);
7181
7339
  checks.push({
7182
7340
  section: "Publish URL",
@@ -7186,7 +7344,7 @@ async function handleDoctor(args2) {
7186
7344
  });
7187
7345
  }
7188
7346
  if (hasWorkflow) {
7189
- const wfContent = fs8.readFileSync(workflowPath, "utf-8");
7347
+ const wfContent = fs9.readFileSync(workflowPath, "utf-8");
7190
7348
  workflowApiUrl = parseApiUrlFromWorkflow(wfContent);
7191
7349
  checks.push({
7192
7350
  section: "Publish URL",
@@ -7345,8 +7503,8 @@ async function handleDoctor(args2) {
7345
7503
  }
7346
7504
 
7347
7505
  // src/commands/nav.ts
7348
- import * as fs9 from "node:fs";
7349
- import * as path9 from "node:path";
7506
+ import * as fs10 from "node:fs";
7507
+ import * as path10 from "node:path";
7350
7508
  function parseNavGenerateArgs(args2) {
7351
7509
  const opts = {};
7352
7510
  for (let i = 0; i < args2.length; i++) {
@@ -7365,9 +7523,9 @@ function parseNavGenerateArgs(args2) {
7365
7523
  }
7366
7524
  async function handleNavGenerate(args2) {
7367
7525
  const opts = parseNavGenerateArgs(args2);
7368
- const docsDir = path9.resolve(opts.docsDir ?? "docs");
7369
- const configPath = path9.join(docsDir, "nrdocs.yml");
7370
- if (!fs9.existsSync(configPath)) {
7526
+ const docsDir = path10.resolve(opts.docsDir ?? "docs");
7527
+ const configPath = path10.join(docsDir, "nrdocs.yml");
7528
+ if (!fs10.existsSync(configPath)) {
7371
7529
  console.error(`Error: Config file not found: ${configPath}`);
7372
7530
  console.error("Run: nrdocs init");
7373
7531
  process.exit(10);
@@ -7400,7 +7558,7 @@ async function handleNavGenerate(args2) {
7400
7558
  }
7401
7559
  writeNavToConfig(loaded.configPath, entries);
7402
7560
  if (!opts.json) {
7403
- console.log(`Generated navigation for ${entries.length} page(s) in ${path9.relative(process.cwd(), configPath)}`);
7561
+ console.log(`Generated navigation for ${entries.length} page(s) in ${path10.relative(process.cwd(), configPath)}`);
7404
7562
  console.log("Edit the file to reorder or rename entries, then run publish.");
7405
7563
  }
7406
7564
  }
@@ -7408,8 +7566,8 @@ async function handleNavGenerate(args2) {
7408
7566
  // src/commands/deploy.ts
7409
7567
  import * as readline3 from "node:readline";
7410
7568
  import * as crypto from "node:crypto";
7411
- import * as fs10 from "node:fs";
7412
- import * as path10 from "node:path";
7569
+ import * as fs11 from "node:fs";
7570
+ import * as path11 from "node:path";
7413
7571
  import { execSync } from "node:child_process";
7414
7572
  function parseDeployArgs(args2) {
7415
7573
  const opts = {};
@@ -7478,14 +7636,14 @@ function normalizeUrl2(url) {
7478
7636
  }
7479
7637
  function findWorkerDir() {
7480
7638
  const candidates = [
7481
- path10.resolve("packages/worker"),
7482
- path10.resolve("../worker")
7639
+ path11.resolve("packages/worker"),
7640
+ path11.resolve("../worker")
7483
7641
  ];
7484
- const cliDir = process.argv[1] ? path10.dirname(process.argv[1]) : process.cwd();
7485
- candidates.push(path10.resolve(cliDir, "../../../worker"));
7486
- candidates.push(path10.resolve(cliDir, "../../../../packages/worker"));
7642
+ const cliDir = process.argv[1] ? path11.dirname(process.argv[1]) : process.cwd();
7643
+ candidates.push(path11.resolve(cliDir, "../../../worker"));
7644
+ candidates.push(path11.resolve(cliDir, "../../../../packages/worker"));
7487
7645
  for (const candidate of candidates) {
7488
- if (fs10.existsSync(path10.join(candidate, "src", "index.ts"))) {
7646
+ if (fs11.existsSync(path11.join(candidate, "src", "index.ts"))) {
7489
7647
  return candidate;
7490
7648
  }
7491
7649
  }
@@ -7628,12 +7786,12 @@ bucket_name = "${names.r2}"
7628
7786
  [vars]
7629
7787
  BASE_URL = "${baseUrl}"
7630
7788
  `;
7631
- const wranglerPath = path10.join(workerDir, "wrangler.toml");
7632
- fs10.writeFileSync(wranglerPath, wranglerToml);
7789
+ const wranglerPath = path11.join(workerDir, "wrangler.toml");
7790
+ fs11.writeFileSync(wranglerPath, wranglerToml);
7633
7791
  console.log("\u2705 wrangler.toml generated");
7634
7792
  console.log("Applying D1 migrations...");
7635
- const migrationsDir = path10.join(workerDir, "migrations");
7636
- if (fs10.existsSync(migrationsDir)) {
7793
+ const migrationsDir = path11.join(workerDir, "migrations");
7794
+ if (fs11.existsSync(migrationsDir)) {
7637
7795
  const migResult = runSilent(`npx wrangler d1 migrations apply ${names.d1} --remote --config "${wranglerPath}"`);
7638
7796
  if (migResult.ok) {
7639
7797
  console.log("\u2705 Migrations applied");