nrdocs 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.mjs +86 -32
  2. package/package.json +1 -1
package/dist/bin.mjs CHANGED
@@ -6108,9 +6108,33 @@ function rewriteMdLink(href, basePath, owner, repo) {
6108
6108
  }
6109
6109
 
6110
6110
  // src/renderer/template.ts
6111
+ function extractToc(html) {
6112
+ const toc = [];
6113
+ const regex = /<h([2-3])[^>]*id="([^"]*)"[^>]*>(.*?)<\/h[2-3]>/gi;
6114
+ let match2;
6115
+ while ((match2 = regex.exec(html)) !== null) {
6116
+ toc.push({
6117
+ level: parseInt(match2[1], 10),
6118
+ id: match2[2],
6119
+ text: match2[3].replace(/<[^>]*>/g, "")
6120
+ });
6121
+ }
6122
+ return toc;
6123
+ }
6124
+ function addHeadingIds(html) {
6125
+ return html.replace(/<h([2-3])([^>]*)>(.*?)<\/h[2-3]>/gi, (_match, level, attrs, text2) => {
6126
+ if (attrs.includes("id=")) return _match;
6127
+ const plainText = text2.replace(/<[^>]*>/g, "");
6128
+ const id = plainText.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
6129
+ return `<h${level} id="${id}"${attrs}>${text2}</h${level}>`;
6130
+ });
6131
+ }
6111
6132
  function wrapInTemplate(options) {
6112
6133
  const { title, siteTitle, content, nav, canonicalUrl, baseUrl } = options;
6113
6134
  const pageTitle = title === siteTitle ? siteTitle : `${title} - ${siteTitle}`;
6135
+ const contentWithIds = addHeadingIds(content);
6136
+ const toc = extractToc(contentWithIds);
6137
+ const hasToc = toc.length > 1;
6114
6138
  return `<!DOCTYPE html>
6115
6139
  <html lang="en">
6116
6140
  <head>
@@ -6119,34 +6143,46 @@ function wrapInTemplate(options) {
6119
6143
  <meta http-equiv="X-Content-Type-Options" content="nosniff">
6120
6144
  <meta http-equiv="X-Frame-Options" content="DENY">
6121
6145
  <meta name="referrer" content="no-referrer">
6146
+ <meta name="generator" content="nrdocs">
6122
6147
  <title>${escapeHtml2(pageTitle)}</title>
6123
6148
  <link rel="canonical" href="${escapeHtml2(canonicalUrl)}">
6124
6149
  <style>
6125
6150
  *{margin:0;padding:0;box-sizing:border-box}
6126
- body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;line-height:1.6;color:#1a1a1a;display:flex;min-height:100vh}
6127
- nav.sidebar{width:260px;padding:1.5rem;border-right:1px solid #e0e0e0;background:#fafafa;overflow-y:auto;flex-shrink:0}
6151
+ 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}
6152
+ 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}
6128
6153
  nav.sidebar .site-title{font-weight:700;font-size:1.1rem;margin-bottom:1rem;color:#111}
6129
6154
  nav.sidebar ul{list-style:none}
6130
6155
  nav.sidebar li{margin-bottom:0.25rem}
6131
- nav.sidebar a{color:#333;text-decoration:none;padding:0.25rem 0.5rem;display:block;border-radius:4px}
6156
+ nav.sidebar a{color:#333;text-decoration:none;padding:0.3rem 0.6rem;display:block;border-radius:4px;font-size:0.95rem}
6132
6157
  nav.sidebar a:hover{background:#e8e8e8}
6133
6158
  nav.sidebar a.active{background:#e0e7ff;color:#1d4ed8;font-weight:500}
6134
- main{flex:1;padding:2rem 3rem;max-width:52rem;overflow-wrap:break-word}
6135
- main h1{font-size:2rem;margin-bottom:1rem;border-bottom:1px solid #e0e0e0;padding-bottom:0.5rem}
6136
- main h2{font-size:1.5rem;margin-top:2rem;margin-bottom:0.75rem}
6137
- main h3{font-size:1.25rem;margin-top:1.5rem;margin-bottom:0.5rem}
6138
- main p{margin-bottom:1rem}
6159
+ .content-wrapper{flex:1;display:flex;min-width:0}
6160
+ main{flex:1;padding:2.5rem 3rem;max-width:52rem;min-width:0;overflow-wrap:break-word}
6161
+ main h1{font-size:2.2rem;margin-bottom:1.2rem;border-bottom:1px solid #e0e0e0;padding-bottom:0.5rem;line-height:1.3}
6162
+ main h2{font-size:1.6rem;margin-top:2.5rem;margin-bottom:0.75rem;line-height:1.3}
6163
+ main h3{font-size:1.3rem;margin-top:1.8rem;margin-bottom:0.5rem;line-height:1.4}
6164
+ main p{margin-bottom:1.1rem}
6139
6165
  main a{color:#1d4ed8;text-decoration:underline}
6140
- main code{background:#f3f4f6;padding:0.15rem 0.35rem;border-radius:3px;font-size:0.9em}
6141
- main pre{background:#1e1e1e;color:#d4d4d4;padding:1rem;border-radius:6px;overflow-x:auto;margin-bottom:1rem}
6142
- main pre code{background:none;padding:0;color:inherit}
6143
- main table{border-collapse:collapse;width:100%;margin-bottom:1rem}
6144
- main th,main td{border:1px solid #d0d0d0;padding:0.5rem 0.75rem;text-align:left}
6166
+ main code{background:#f3f4f6;padding:0.2rem 0.4rem;border-radius:3px;font-size:0.88em}
6167
+ 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}
6168
+ main pre code{background:none;padding:0;color:inherit;font-size:inherit}
6169
+ main table{border-collapse:collapse;width:100%;margin-bottom:1.2rem}
6170
+ main th,main td{border:1px solid #d0d0d0;padding:0.6rem 0.85rem;text-align:left}
6145
6171
  main th{background:#f5f5f5;font-weight:600}
6146
- main img{max-width:100%;height:auto}
6147
- main blockquote{border-left:4px solid #d0d0d0;padding-left:1rem;margin-bottom:1rem;color:#555}
6148
- main ul,main ol{margin-bottom:1rem;padding-left:1.5rem}
6149
- @media(max-width:768px){body{flex-direction:column}nav.sidebar{width:100%;border-right:none;border-bottom:1px solid #e0e0e0}main{padding:1rem}}
6172
+ main img{max-width:100%;height:auto;border-radius:4px}
6173
+ main blockquote{border-left:4px solid #d0d0d0;padding-left:1rem;margin-bottom:1.1rem;color:#555;font-style:italic}
6174
+ main ul,main ol{margin-bottom:1.1rem;padding-left:1.5rem}
6175
+ main li{margin-bottom:0.3rem}
6176
+ 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}
6177
+ aside.toc .toc-title{font-size:0.8rem;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#666;margin-bottom:0.75rem}
6178
+ aside.toc ul{list-style:none}
6179
+ aside.toc li{margin-bottom:0.3rem}
6180
+ aside.toc a{color:#555;text-decoration:none;font-size:0.85rem;display:block;padding:0.15rem 0;border-radius:2px}
6181
+ aside.toc a:hover{color:#1d4ed8}
6182
+ aside.toc .toc-h3{padding-left:0.75rem}
6183
+ footer{padding:1.5rem 3rem;border-top:1px solid #e8e8e8;color:#888;font-size:0.8rem;text-align:center}
6184
+ @media(max-width:1100px){aside.toc{display:none}}
6185
+ @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}}
6150
6186
  </style>
6151
6187
  </head>
6152
6188
  <body>
@@ -6156,12 +6192,28 @@ main ul,main ol{margin-bottom:1rem;padding-left:1.5rem}
6156
6192
  ${renderNavItems(nav, baseUrl)}
6157
6193
  </ul>
6158
6194
  </nav>
6195
+ <div class="content-wrapper">
6159
6196
  <main>
6160
- ${content}
6197
+ ${contentWithIds}
6198
+ <footer>Generated with <a href="https://github.com/noam-r/nrdocs">nrdocs</a></footer>
6161
6199
  </main>
6200
+ ${hasToc ? renderToc(toc) : ""}
6201
+ </div>
6162
6202
  </body>
6163
6203
  </html>`;
6164
6204
  }
6205
+ function renderToc(toc) {
6206
+ const items = toc.map((entry) => {
6207
+ const cls = entry.level === 3 ? ' class="toc-h3"' : "";
6208
+ return `<li${cls}><a href="#${escapeHtml2(entry.id)}">${escapeHtml2(entry.text)}</a></li>`;
6209
+ }).join("\n");
6210
+ return `<aside class="toc">
6211
+ <div class="toc-title">On this page</div>
6212
+ <ul>
6213
+ ${items}
6214
+ </ul>
6215
+ </aside>`;
6216
+ }
6165
6217
  function renderNavItems(items, baseUrl) {
6166
6218
  return items.map((item) => {
6167
6219
  const href = baseUrl + item.href;
@@ -6377,46 +6429,46 @@ var ApiClient = class {
6377
6429
  if (filters?.access) params.set("access", filters.access);
6378
6430
  if (filters?.owner) params.set("owner", filters.owner);
6379
6431
  const qs = params.toString();
6380
- return this.request("GET", `/api/operator/repos${qs ? `?${qs}` : ""}`);
6432
+ return this.request("GET", `/api/repos${qs ? `?${qs}` : ""}`);
6381
6433
  }
6382
6434
  async getRepo(owner, repo) {
6383
- return this.request("GET", `/api/operator/repos/${owner}/${repo}`);
6435
+ return this.request("GET", `/api/repos/${owner}/${repo}`);
6384
6436
  }
6385
6437
  async approveRepo(owner, repo, accessMode) {
6386
- return this.request("POST", `/api/operator/repos/${owner}/${repo}/approve`, {
6438
+ return this.request("POST", `/api/repos/${owner}/${repo}/approve`, {
6387
6439
  access_mode: accessMode
6388
6440
  });
6389
6441
  }
6390
6442
  async disableRepo(owner, repo, reason) {
6391
- return this.request("POST", `/api/operator/repos/${owner}/${repo}/disable`, {
6443
+ return this.request("POST", `/api/repos/${owner}/${repo}/disable`, {
6392
6444
  reason: reason ?? void 0
6393
6445
  });
6394
6446
  }
6395
6447
  async setAccess(owner, repo, accessMode) {
6396
- return this.request("PUT", `/api/operator/repos/${owner}/${repo}/access`, {
6448
+ return this.request("POST", `/api/repos/${owner}/${repo}/access`, {
6397
6449
  access_mode: accessMode
6398
6450
  });
6399
6451
  }
6400
6452
  async setPassword(owner, repo, password) {
6401
- return this.request("PUT", `/api/operator/repos/${owner}/${repo}/password`, {
6453
+ return this.request("POST", `/api/repos/${owner}/${repo}/password`, {
6402
6454
  password
6403
6455
  });
6404
6456
  }
6405
6457
  async listRules() {
6406
- return this.request("GET", "/api/operator/rules");
6458
+ return this.request("GET", "/api/auto-approval-rules");
6407
6459
  }
6408
6460
  async addRule(pattern, accessMode, applyExisting) {
6409
- return this.request("POST", "/api/operator/rules", {
6461
+ return this.request("POST", "/api/auto-approval-rules", {
6410
6462
  pattern,
6411
6463
  access_mode: accessMode,
6412
6464
  apply_existing: applyExisting ?? false
6413
6465
  });
6414
6466
  }
6415
6467
  async removeRule(ruleId) {
6416
- return this.request("DELETE", `/api/operator/rules/${ruleId}`);
6468
+ return this.request("DELETE", `/api/auto-approval-rules/${ruleId}`);
6417
6469
  }
6418
6470
  async getStatus(owner, repo) {
6419
- return this.request("GET", `/api/operator/repos/${owner}/${repo}/status`);
6471
+ return this.request("GET", `/api/repos/${owner}/${repo}`);
6420
6472
  }
6421
6473
  async getOperatorMe() {
6422
6474
  return this.request("GET", "/api/operator/me");
@@ -6531,13 +6583,15 @@ async function handlePublish(args2) {
6531
6583
  process.exit(12);
6532
6584
  }
6533
6585
  const { owner, repo } = repoInfo;
6586
+ const ownerLower = owner.toLowerCase();
6587
+ const repoLower = repo.toLowerCase();
6534
6588
  const siteTitle = validation.title || "Documentation";
6535
6589
  const apiUrl = validation.apiUrl || process.env["NRDOCS_API_URL"] || "";
6536
6590
  if (!apiUrl) {
6537
6591
  console.error("Error: No API URL configured. Set api_url in nrdocs.yml or NRDOCS_API_URL env var.");
6538
6592
  process.exit(10);
6539
6593
  }
6540
- console.log(`Publishing docs for ${owner}/${repo}...`);
6594
+ console.log(`Publishing docs for ${ownerLower}/${repoLower}...`);
6541
6595
  console.log(`Docs directory: ${docsDir}`);
6542
6596
  console.log(`Site title: ${siteTitle}`);
6543
6597
  console.log("Rendering Markdown...");
@@ -6545,8 +6599,8 @@ async function handlePublish(args2) {
6545
6599
  docsDir,
6546
6600
  siteTitle,
6547
6601
  baseUrl: apiUrl,
6548
- owner,
6549
- repo
6602
+ owner: ownerLower,
6603
+ repo: repoLower
6550
6604
  });
6551
6605
  console.log(`Rendered ${site.files.length} files.`);
6552
6606
  console.log("Creating archive...");
@@ -6571,7 +6625,7 @@ async function handlePublish(args2) {
6571
6625
  const result = await client.publish(formData);
6572
6626
  if (result.ok) {
6573
6627
  console.log("Published successfully!");
6574
- console.log(`View at: ${apiUrl}/${owner}/${repo}/`);
6628
+ console.log(`View at: ${apiUrl}/${ownerLower}/${repoLower}/`);
6575
6629
  } else {
6576
6630
  console.error(`Error: Upload failed \u2014 ${result.error?.message || "unknown error"}`);
6577
6631
  process.exit(14);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nrdocs",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "CLI for nrdocs - serverless docs publishing for private GitHub repos",
5
5
  "type": "module",
6
6
  "bin": {