nrdocs 0.1.6 → 0.1.7

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,33 @@ 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 initMermaid(){
6208
+ if(typeof mermaid==='undefined')return;
6209
+ mermaid.initialize({startOnLoad:true,theme:theme()==='dark'?'dark':'default'});
6210
+ mermaid.run();
6211
+ }
6212
+ document.addEventListener('DOMContentLoaded',initMermaid);
6213
+ document.addEventListener('nrdocs-theme-change',initMermaid);
6214
+ })();
6215
+ </script>` : "";
6179
6216
  return `<!DOCTYPE html>
6180
6217
  <html lang="en">
6181
6218
  <head>
@@ -6187,48 +6224,97 @@ function wrapInTemplate(options) {
6187
6224
  <meta name="generator" content="nrdocs">
6188
6225
  <title>${escapeHtml2(pageTitle)}</title>
6189
6226
  <link rel="canonical" href="${escapeHtml2(canonicalUrl)}">
6227
+ <script>
6228
+ (function(){try{var s=localStorage.getItem('nrdocs-theme');if(s==='light'||s==='dark')document.documentElement.dataset.theme=s;}catch(e){}})();
6229
+ </script>
6190
6230
  <style>
6231
+ :root{
6232
+ --text:#1a1a1a;--text-muted:#555;--text-footer:#888;
6233
+ --bg-body:#fff;--bg-sidebar:#fafafa;--bg-hover:#e8e8e8;--bg-active:#e0e7ff;
6234
+ --border:#e0e0e0;--border-light:#e8e8e8;
6235
+ --link:#1d4ed8;--link-active:#1d4ed8;
6236
+ --code-bg:#f3f4f6;--pre-bg:#1e1e1e;--pre-text:#d4d4d4;
6237
+ --th-bg:#f5f5f5;--blockquote:#555;
6238
+ --toc-title:#666;--toc-link:#555;
6239
+ }
6240
+ @media(prefers-color-scheme:dark){
6241
+ html:not([data-theme]){
6242
+ --text:#e5e5e5;--text-muted:#a3a3a3;--text-footer:#737373;
6243
+ --bg-body:#0a0a0a;--bg-sidebar:#111;--bg-hover:#262626;--bg-active:#1e3a5f;
6244
+ --border:#333;--border-light:#262626;
6245
+ --link:#60a5fa;--link-active:#93c5fd;
6246
+ --code-bg:#262626;--pre-bg:#1a1a1a;--pre-text:#d4d4d4;
6247
+ --th-bg:#1a1a1a;--blockquote:#a3a3a3;
6248
+ --toc-title:#a3a3a3;--toc-link:#a3a3a3;
6249
+ }
6250
+ }
6251
+ html[data-theme="dark"]{
6252
+ --text:#e5e5e5;--text-muted:#a3a3a3;--text-footer:#737373;
6253
+ --bg-body:#0a0a0a;--bg-sidebar:#111;--bg-hover:#262626;--bg-active:#1e3a5f;
6254
+ --border:#333;--border-light:#262626;
6255
+ --link:#60a5fa;--link-active:#93c5fd;
6256
+ --code-bg:#262626;--pre-bg:#1a1a1a;--pre-text:#d4d4d4;
6257
+ --th-bg:#1a1a1a;--blockquote:#a3a3a3;
6258
+ --toc-title:#a3a3a3;--toc-link:#a3a3a3;
6259
+ }
6260
+ html[data-theme="light"]{
6261
+ --text:#1a1a1a;--text-muted:#555;--text-footer:#888;
6262
+ --bg-body:#fff;--bg-sidebar:#fafafa;--bg-hover:#e8e8e8;--bg-active:#e0e7ff;
6263
+ --border:#e0e0e0;--border-light:#e8e8e8;
6264
+ --link:#1d4ed8;--link-active:#1d4ed8;
6265
+ --code-bg:#f3f4f6;--pre-bg:#1e1e1e;--pre-text:#d4d4d4;
6266
+ --th-bg:#f5f5f5;--blockquote:#555;
6267
+ --toc-title:#666;--toc-link:#555;
6268
+ }
6191
6269
  *{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}
6270
+ 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}
6271
+ 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}
6272
+ .site-header{display:flex;align-items:center;justify-content:space-between;gap:0.5rem;margin-bottom:1rem}
6273
+ nav.sidebar .site-title{font-weight:700;font-size:1.1rem;color:var(--text);flex:1;min-width:0}
6274
+ #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}
6275
+ #theme-toggle:hover{background:var(--bg-active)}
6195
6276
  nav.sidebar ul{list-style:none}
6196
6277
  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}
6278
+ nav.sidebar a{color:var(--text-muted);text-decoration:none;padding:0.3rem 0.6rem;display:block;border-radius:4px;font-size:0.95rem}
6279
+ nav.sidebar a:hover{background:var(--bg-hover);color:var(--text)}
6280
+ nav.sidebar a.active{background:var(--bg-active);color:var(--link-active);font-weight:500}
6200
6281
  .content-wrapper{flex:1;display:flex;min-width:0}
6201
6282
  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}
6283
+ 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)}
6284
+ main h2{font-size:1.6rem;margin-top:2.5rem;margin-bottom:0.75rem;line-height:1.3;color:var(--text)}
6285
+ main h3{font-size:1.3rem;margin-top:1.8rem;margin-bottom:0.5rem;line-height:1.4;color:var(--text)}
6205
6286
  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}
6287
+ main a{color:var(--link);text-decoration:underline}
6288
+ main code{background:var(--code-bg);padding:0.2rem 0.4rem;border-radius:3px;font-size:0.88em;color:var(--text)}
6289
+ 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
6290
  main pre code{background:none;padding:0;color:inherit;font-size:inherit}
6291
+ main pre.mermaid{background:transparent;color:var(--text);padding:0;margin:1.5rem 0;overflow-x:auto}
6210
6292
  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}
6293
+ main th,main td{border:1px solid var(--border);padding:0.6rem 0.85rem;text-align:left;color:var(--text)}
6294
+ main th{background:var(--th-bg);font-weight:600}
6213
6295
  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}
6296
+ main blockquote{border-left:4px solid var(--border);padding-left:1rem;margin-bottom:1.1rem;color:var(--blockquote);font-style:italic}
6215
6297
  main ul,main ol{margin-bottom:1.1rem;padding-left:1.5rem}
6216
6298
  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}
6299
+ 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)}
6300
+ 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
6301
  aside.toc ul{list-style:none}
6220
6302
  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}
6303
+ aside.toc a{color:var(--toc-link);text-decoration:none;font-size:0.85rem;display:block;padding:0.15rem 0;border-radius:2px}
6304
+ aside.toc a:hover{color:var(--link)}
6223
6305
  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}
6306
+ 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}
6307
+ footer a{color:var(--link)}
6225
6308
  @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}}
6309
+ @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
6310
  </style>
6228
6311
  </head>
6229
6312
  <body>
6230
6313
  <nav class="sidebar">
6314
+ <div class="site-header">
6231
6315
  <div class="site-title">${escapeHtml2(siteTitle)}</div>
6316
+ <button type="button" id="theme-toggle" aria-label="Toggle color theme" title="Toggle light/dark mode">&#9789;</button>
6317
+ </div>
6232
6318
  <ul>
6233
6319
  ${renderNavItems(nav, baseUrl)}
6234
6320
  </ul>
@@ -6240,6 +6326,32 @@ ${contentWithIds}
6240
6326
  </main>
6241
6327
  ${hasToc ? renderToc(toc) : ""}
6242
6328
  </div>
6329
+ <script>
6330
+ (function(){
6331
+ var key='nrdocs-theme';
6332
+ var root=document.documentElement;
6333
+ function resolved(){
6334
+ var t=root.dataset.theme;
6335
+ if(t==='dark'||t==='light')return t;
6336
+ return window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';
6337
+ }
6338
+ function apply(next){
6339
+ root.dataset.theme=next;
6340
+ try{localStorage.setItem(key,next);}catch(e){}
6341
+ document.dispatchEvent(new CustomEvent('nrdocs-theme-change',{detail:{theme:next}}));
6342
+ var btn=document.getElementById('theme-toggle');
6343
+ if(btn)btn.textContent=next==='dark'?'\\u2600':'\\u263E';
6344
+ }
6345
+ var btn=document.getElementById('theme-toggle');
6346
+ if(btn){
6347
+ btn.textContent=resolved()==='dark'?'\\u2600':'\\u263E';
6348
+ btn.addEventListener('click',function(){
6349
+ apply(resolved()==='dark'?'light':'dark');
6350
+ });
6351
+ }
6352
+ })();
6353
+ </script>
6354
+ ${mermaidBlock}
6243
6355
  </body>
6244
6356
  </html>`;
6245
6357
  }
@@ -6306,6 +6418,35 @@ function collectFromDir(dir, rootDir, results) {
6306
6418
  }
6307
6419
  }
6308
6420
 
6421
+ // src/renderer/mermaid-runtime.ts
6422
+ import * as fs5 from "node:fs";
6423
+ import * as path6 from "node:path";
6424
+ import { fileURLToPath } from "node:url";
6425
+ var __dirname = path6.dirname(fileURLToPath(import.meta.url));
6426
+ var MERMAID_RUNTIME_REL = "runtime/mermaid.min.js";
6427
+ var MERMAID_ARTIFACT_PATH = "_nrdocs/mermaid.min.js";
6428
+ function mermaidRuntimeCandidates() {
6429
+ return [
6430
+ path6.join(__dirname, MERMAID_RUNTIME_REL),
6431
+ path6.join(__dirname, "../../dist/runtime/mermaid.min.js")
6432
+ ];
6433
+ }
6434
+ function loadMermaidRuntime() {
6435
+ for (const candidate of mermaidRuntimeCandidates()) {
6436
+ if (fs5.existsSync(candidate)) {
6437
+ return fs5.readFileSync(candidate);
6438
+ }
6439
+ }
6440
+ throw new Error(
6441
+ "Mermaid runtime not found. Run: pnpm --filter nrdocs bundle (or pnpm bundle in packages/cli)"
6442
+ );
6443
+ }
6444
+ function mermaidScriptSrcForOutput(outputPath) {
6445
+ const depth = outputPath.split("/").length - 1;
6446
+ const prefix = depth > 0 ? "../".repeat(depth) : "";
6447
+ return `${prefix}${MERMAID_ARTIFACT_PATH}`;
6448
+ }
6449
+
6309
6450
  // src/renderer/index.ts
6310
6451
  function resolveNavItems(resolvedDocsDir, nav, indexPath) {
6311
6452
  if (nav && nav !== "auto" && Array.isArray(nav)) {
@@ -6315,15 +6456,18 @@ function resolveNavItems(resolvedDocsDir, nav, indexPath) {
6315
6456
  }
6316
6457
  async function renderSite(options) {
6317
6458
  const { docsDir, siteTitle, baseUrl, owner, repo, nav, indexPath = "index.md" } = options;
6318
- const resolvedDocsDir = path6.resolve(docsDir);
6459
+ const resolvedDocsDir = path7.resolve(docsDir);
6319
6460
  const navItems = resolveNavItems(resolvedDocsDir, nav, indexPath);
6320
6461
  const siteBase = `/${owner}/${repo}/`;
6321
6462
  const renderedFiles = [];
6463
+ let siteHasMermaid = false;
6322
6464
  for (const navItem of navItems) {
6323
- const filePath = path6.join(resolvedDocsDir, navItem.path);
6324
- const markdownContent = fs5.readFileSync(filePath, "utf-8");
6465
+ const filePath = path7.join(resolvedDocsDir, navItem.path);
6466
+ const markdownContent = fs6.readFileSync(filePath, "utf-8");
6467
+ const pageHasMermaid = contentHasMermaid(markdownContent);
6468
+ if (pageHasMermaid) siteHasMermaid = true;
6325
6469
  let html = renderMarkdown(markdownContent);
6326
- const fileDir = path6.dirname(navItem.path);
6470
+ const fileDir = path7.dirname(navItem.path);
6327
6471
  const baseLinkPath = fileDir === "." ? "" : fileDir;
6328
6472
  html = rewriteLinks(html, baseLinkPath, owner, repo);
6329
6473
  const pageTitle = extractTitle(markdownContent, navItem.path);
@@ -6332,20 +6476,28 @@ async function renderSite(options) {
6332
6476
  ...item,
6333
6477
  active: item.path === navItem.path
6334
6478
  }));
6479
+ const outputPath = navItem.href === "" ? "index.html" : navItem.href.replace(/\/$/, "") + "/index.html";
6335
6480
  const fullHtml = wrapInTemplate({
6336
6481
  title: pageTitle,
6337
6482
  siteTitle,
6338
6483
  content: html,
6339
6484
  nav: navWithActive,
6340
6485
  canonicalUrl,
6341
- baseUrl: siteBase
6486
+ baseUrl: siteBase,
6487
+ includeMermaid: pageHasMermaid,
6488
+ mermaidScriptSrc: pageHasMermaid ? mermaidScriptSrcForOutput(outputPath) : null
6342
6489
  });
6343
- const outputPath = navItem.href === "" ? "index.html" : navItem.href.replace(/\/$/, "") + "/index.html";
6344
6490
  renderedFiles.push({
6345
6491
  path: outputPath,
6346
6492
  content: Buffer.from(fullHtml, "utf-8")
6347
6493
  });
6348
6494
  }
6495
+ if (siteHasMermaid) {
6496
+ renderedFiles.push({
6497
+ path: MERMAID_ARTIFACT_PATH,
6498
+ content: loadMermaidRuntime()
6499
+ });
6500
+ }
6349
6501
  const assets = collectAssets(resolvedDocsDir);
6350
6502
  renderedFiles.push(...assets);
6351
6503
  const manifest = {
@@ -6442,8 +6594,8 @@ function normalizeApiBaseUrl(url) {
6442
6594
  }
6443
6595
  function buildApiUrl(baseUrl, apiPath) {
6444
6596
  const { url } = normalizeApiBaseUrl(baseUrl);
6445
- const path11 = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
6446
- return `${url}${path11}`;
6597
+ const path12 = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
6598
+ return `${url}${path12}`;
6447
6599
  }
6448
6600
  function extractFetchError(err) {
6449
6601
  if (!(err instanceof Error)) {
@@ -6691,8 +6843,8 @@ var ApiClient = class {
6691
6843
  }
6692
6844
  };
6693
6845
  }
6694
- async request(method, path11, body, timeoutMs = DEFAULT_TIMEOUT_MS) {
6695
- const url = buildApiUrl(this.baseUrl, path11);
6846
+ async request(method, path12, body, timeoutMs = DEFAULT_TIMEOUT_MS) {
6847
+ const url = buildApiUrl(this.baseUrl, path12);
6696
6848
  const controller = new AbortController();
6697
6849
  const timer = setTimeout(() => controller.abort(), timeoutMs);
6698
6850
  const init = {
@@ -6823,21 +6975,21 @@ var ApiClient = class {
6823
6975
  };
6824
6976
 
6825
6977
  // src/config/docs-config.ts
6826
- import * as fs6 from "node:fs";
6827
- import * as path7 from "node:path";
6978
+ import * as fs7 from "node:fs";
6979
+ import * as path8 from "node:path";
6828
6980
  import YAML from "yaml";
6829
6981
  function loadDocsConfig(docsDir) {
6830
- const configPath = path7.resolve(docsDir, "nrdocs.yml");
6831
- if (!fs6.existsSync(configPath)) {
6982
+ const configPath = path8.resolve(docsDir, "nrdocs.yml");
6983
+ if (!fs7.existsSync(configPath)) {
6832
6984
  throw new Error(`Config file not found: ${configPath}`);
6833
6985
  }
6834
- const raw = fs6.readFileSync(configPath, "utf-8");
6986
+ const raw = fs7.readFileSync(configPath, "utf-8");
6835
6987
  const config2 = YAML.parse(raw);
6836
6988
  if (!config2 || typeof config2 !== "object") {
6837
6989
  throw new Error(`Invalid config: ${configPath}`);
6838
6990
  }
6839
6991
  const sourceDir = config2.content?.source_dir ?? ".";
6840
- const contentDir = path7.resolve(docsDir, sourceDir);
6992
+ const contentDir = path8.resolve(docsDir, sourceDir);
6841
6993
  return { config: config2, configPath, contentDir };
6842
6994
  }
6843
6995
  function hasExplicitNav(config2) {
@@ -6883,8 +7035,8 @@ function validateNavPaths(entries, contentDir) {
6883
7035
  errors.push(`Duplicate nav path: ${p}`);
6884
7036
  }
6885
7037
  seen.add(p);
6886
- const full = path7.join(contentDir, p);
6887
- if (!fs6.existsSync(full)) {
7038
+ const full = path8.join(contentDir, p);
7039
+ if (!fs7.existsSync(full)) {
6888
7040
  errors.push(`Nav path not found: ${p}`);
6889
7041
  }
6890
7042
  if (e.children?.length) walk(e.children);
@@ -6894,7 +7046,7 @@ function validateNavPaths(entries, contentDir) {
6894
7046
  return { valid: errors.length === 0, errors };
6895
7047
  }
6896
7048
  function writeNavToConfig(configPath, navEntries) {
6897
- let raw = fs6.readFileSync(configPath, "utf-8");
7049
+ let raw = fs7.readFileSync(configPath, "utf-8");
6898
7050
  raw = raw.replace(/^# content\.nav generated by: nrdocs nav generate\n/gm, "");
6899
7051
  const config2 = YAML.parse(raw);
6900
7052
  if (!config2 || typeof config2 !== "object") {
@@ -6907,7 +7059,7 @@ function writeNavToConfig(configPath, navEntries) {
6907
7059
  const doc = new YAML.Document(config2);
6908
7060
  const header = "# content.nav generated by: nrdocs nav generate\n";
6909
7061
  const body = doc.toString();
6910
- fs6.writeFileSync(configPath, header + body, "utf-8");
7062
+ fs7.writeFileSync(configPath, header + body, "utf-8");
6911
7063
  }
6912
7064
  function formatNavYaml(navEntries) {
6913
7065
  const partial = {
@@ -6932,10 +7084,10 @@ function parsePublishArgs(args2) {
6932
7084
  return opts;
6933
7085
  }
6934
7086
  function validateConfig2(configPath) {
6935
- if (!fs7.existsSync(configPath)) {
7087
+ if (!fs8.existsSync(configPath)) {
6936
7088
  return { valid: false, error: `Config file not found: ${configPath}` };
6937
7089
  }
6938
- const content = fs7.readFileSync(configPath, "utf-8");
7090
+ const content = fs8.readFileSync(configPath, "utf-8");
6939
7091
  if (!content.includes("site:")) {
6940
7092
  return { valid: false, error: 'Config file missing "site:" section' };
6941
7093
  }
@@ -7115,8 +7267,8 @@ async function handlePublish(args2) {
7115
7267
  }
7116
7268
 
7117
7269
  // src/commands/doctor.ts
7118
- import * as fs8 from "node:fs";
7119
- import * as path8 from "node:path";
7270
+ import * as fs9 from "node:fs";
7271
+ import * as path9 from "node:path";
7120
7272
  function parseDoctorArgs(args2) {
7121
7273
  const opts = {};
7122
7274
  for (const arg of args2) {
@@ -7126,11 +7278,11 @@ function parseDoctorArgs(args2) {
7126
7278
  return opts;
7127
7279
  }
7128
7280
  function countMarkdownFiles(docsDir) {
7129
- if (!fs8.existsSync(docsDir)) return 0;
7281
+ if (!fs9.existsSync(docsDir)) return 0;
7130
7282
  let count = 0;
7131
7283
  const walk = (dir) => {
7132
- for (const entry of fs8.readdirSync(dir, { withFileTypes: true })) {
7133
- const full = path8.join(dir, entry.name);
7284
+ for (const entry of fs9.readdirSync(dir, { withFileTypes: true })) {
7285
+ const full = path9.join(dir, entry.name);
7134
7286
  if (entry.isDirectory()) walk(full);
7135
7287
  else if (entry.name.endsWith(".md")) count++;
7136
7288
  }
@@ -7142,22 +7294,22 @@ async function handleDoctor(args2) {
7142
7294
  const opts = parseDoctorArgs(args2);
7143
7295
  const inCI = opts.ci || process.env["GITHUB_ACTIONS"] === "true";
7144
7296
  const checks = [];
7145
- const isGitRepo = fs8.existsSync(path8.resolve(".git"));
7297
+ const isGitRepo = fs9.existsSync(path9.resolve(".git"));
7146
7298
  checks.push({
7147
7299
  section: "Repo setup",
7148
7300
  name: "Git repository",
7149
7301
  status: isGitRepo ? "ok" : "fail",
7150
7302
  message: isGitRepo ? "Found .git directory" : "Not a git repository"
7151
7303
  });
7152
- const configPath = path8.resolve("docs", "nrdocs.yml");
7153
- const hasConfig = fs8.existsSync(configPath);
7304
+ const configPath = path9.resolve("docs", "nrdocs.yml");
7305
+ const hasConfig = fs9.existsSync(configPath);
7154
7306
  checks.push({
7155
7307
  section: "Repo setup",
7156
7308
  name: "Docs config",
7157
7309
  status: hasConfig ? "ok" : "fail",
7158
7310
  message: hasConfig ? "Found docs/nrdocs.yml" : "Missing docs/nrdocs.yml \u2014 run: nrdocs init"
7159
7311
  });
7160
- const docsDir = path8.resolve("docs");
7312
+ const docsDir = path9.resolve("docs");
7161
7313
  const mdCount = countMarkdownFiles(docsDir);
7162
7314
  checks.push({
7163
7315
  section: "Repo setup",
@@ -7165,8 +7317,8 @@ async function handleDoctor(args2) {
7165
7317
  status: mdCount > 0 ? "ok" : "warn",
7166
7318
  message: mdCount > 0 ? `${mdCount} markdown file(s) in docs/` : "No .md files in docs/ \u2014 publish will produce an empty site"
7167
7319
  });
7168
- const workflowPath = path8.resolve(".github", "workflows", "nrdocs.yml");
7169
- const hasWorkflow = fs8.existsSync(workflowPath);
7320
+ const workflowPath = path9.resolve(".github", "workflows", "nrdocs.yml");
7321
+ const hasWorkflow = fs9.existsSync(workflowPath);
7170
7322
  checks.push({
7171
7323
  section: "Repo setup",
7172
7324
  name: "GitHub workflow",
@@ -7176,7 +7328,7 @@ async function handleDoctor(args2) {
7176
7328
  let configApiUrl;
7177
7329
  let workflowApiUrl;
7178
7330
  if (hasConfig) {
7179
- const content = fs8.readFileSync(configPath, "utf-8");
7331
+ const content = fs9.readFileSync(configPath, "utf-8");
7180
7332
  configApiUrl = parseApiUrlFromConfig(content);
7181
7333
  checks.push({
7182
7334
  section: "Publish URL",
@@ -7186,7 +7338,7 @@ async function handleDoctor(args2) {
7186
7338
  });
7187
7339
  }
7188
7340
  if (hasWorkflow) {
7189
- const wfContent = fs8.readFileSync(workflowPath, "utf-8");
7341
+ const wfContent = fs9.readFileSync(workflowPath, "utf-8");
7190
7342
  workflowApiUrl = parseApiUrlFromWorkflow(wfContent);
7191
7343
  checks.push({
7192
7344
  section: "Publish URL",
@@ -7345,8 +7497,8 @@ async function handleDoctor(args2) {
7345
7497
  }
7346
7498
 
7347
7499
  // src/commands/nav.ts
7348
- import * as fs9 from "node:fs";
7349
- import * as path9 from "node:path";
7500
+ import * as fs10 from "node:fs";
7501
+ import * as path10 from "node:path";
7350
7502
  function parseNavGenerateArgs(args2) {
7351
7503
  const opts = {};
7352
7504
  for (let i = 0; i < args2.length; i++) {
@@ -7365,9 +7517,9 @@ function parseNavGenerateArgs(args2) {
7365
7517
  }
7366
7518
  async function handleNavGenerate(args2) {
7367
7519
  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)) {
7520
+ const docsDir = path10.resolve(opts.docsDir ?? "docs");
7521
+ const configPath = path10.join(docsDir, "nrdocs.yml");
7522
+ if (!fs10.existsSync(configPath)) {
7371
7523
  console.error(`Error: Config file not found: ${configPath}`);
7372
7524
  console.error("Run: nrdocs init");
7373
7525
  process.exit(10);
@@ -7400,7 +7552,7 @@ async function handleNavGenerate(args2) {
7400
7552
  }
7401
7553
  writeNavToConfig(loaded.configPath, entries);
7402
7554
  if (!opts.json) {
7403
- console.log(`Generated navigation for ${entries.length} page(s) in ${path9.relative(process.cwd(), configPath)}`);
7555
+ console.log(`Generated navigation for ${entries.length} page(s) in ${path10.relative(process.cwd(), configPath)}`);
7404
7556
  console.log("Edit the file to reorder or rename entries, then run publish.");
7405
7557
  }
7406
7558
  }
@@ -7408,8 +7560,8 @@ async function handleNavGenerate(args2) {
7408
7560
  // src/commands/deploy.ts
7409
7561
  import * as readline3 from "node:readline";
7410
7562
  import * as crypto from "node:crypto";
7411
- import * as fs10 from "node:fs";
7412
- import * as path10 from "node:path";
7563
+ import * as fs11 from "node:fs";
7564
+ import * as path11 from "node:path";
7413
7565
  import { execSync } from "node:child_process";
7414
7566
  function parseDeployArgs(args2) {
7415
7567
  const opts = {};
@@ -7478,14 +7630,14 @@ function normalizeUrl2(url) {
7478
7630
  }
7479
7631
  function findWorkerDir() {
7480
7632
  const candidates = [
7481
- path10.resolve("packages/worker"),
7482
- path10.resolve("../worker")
7633
+ path11.resolve("packages/worker"),
7634
+ path11.resolve("../worker")
7483
7635
  ];
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"));
7636
+ const cliDir = process.argv[1] ? path11.dirname(process.argv[1]) : process.cwd();
7637
+ candidates.push(path11.resolve(cliDir, "../../../worker"));
7638
+ candidates.push(path11.resolve(cliDir, "../../../../packages/worker"));
7487
7639
  for (const candidate of candidates) {
7488
- if (fs10.existsSync(path10.join(candidate, "src", "index.ts"))) {
7640
+ if (fs11.existsSync(path11.join(candidate, "src", "index.ts"))) {
7489
7641
  return candidate;
7490
7642
  }
7491
7643
  }
@@ -7628,12 +7780,12 @@ bucket_name = "${names.r2}"
7628
7780
  [vars]
7629
7781
  BASE_URL = "${baseUrl}"
7630
7782
  `;
7631
- const wranglerPath = path10.join(workerDir, "wrangler.toml");
7632
- fs10.writeFileSync(wranglerPath, wranglerToml);
7783
+ const wranglerPath = path11.join(workerDir, "wrangler.toml");
7784
+ fs11.writeFileSync(wranglerPath, wranglerToml);
7633
7785
  console.log("\u2705 wrangler.toml generated");
7634
7786
  console.log("Applying D1 migrations...");
7635
- const migrationsDir = path10.join(workerDir, "migrations");
7636
- if (fs10.existsSync(migrationsDir)) {
7787
+ const migrationsDir = path11.join(workerDir, "migrations");
7788
+ if (fs11.existsSync(migrationsDir)) {
7637
7789
  const migResult = runSilent(`npx wrangler d1 migrations apply ${names.d1} --remote --config "${wranglerPath}"`);
7638
7790
  if (migResult.ok) {
7639
7791
  console.log("\u2705 Migrations applied");