@zoulabo/line-hive 0.2.15 → 0.2.21

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.
@@ -0,0 +1,625 @@
1
+ /**
2
+ * Navigation Browser — server-side file viewer and directory browser.
3
+ *
4
+ * Provides `/nav/view/<path>` and `/nav/ls/<path>` GET routes that render
5
+ * workspace files and directories as HTML pages in LINE's in-app browser.
6
+ * All nav URLs are authenticated via HMAC-SHA256 signed tokens.
7
+ */
8
+ import fs from "fs";
9
+ import path from "path";
10
+ import crypto from "crypto";
11
+ import { marked } from "marked";
12
+ // ─── Token Auth ─────────────────────────────────────────────────────────────
13
+ const DEFAULT_NAV_TTL_MS = 2 * 60 * 60 * 1000; // 2 hours
14
+ const NAV_SESSION_TTL_MS = 12 * 60 * 60 * 1000; // 12 hours
15
+ /** In-memory nav session store. Sessions are ephemeral — server restart invalidates all. */
16
+ const navSessions = new Map(); // sessionId → expiresAt
17
+ /** Create a new nav session and return its ID. */
18
+ export function createNavSession() {
19
+ const sessionId = crypto.randomUUID();
20
+ navSessions.set(sessionId, Date.now() + NAV_SESSION_TTL_MS);
21
+ return sessionId;
22
+ }
23
+ /** Verify a nav session ID. Returns true if valid and not expired. */
24
+ export function verifyNavSession(sessionId) {
25
+ const expiresAt = navSessions.get(sessionId);
26
+ if (!expiresAt)
27
+ return false;
28
+ if (Date.now() > expiresAt) {
29
+ navSessions.delete(sessionId);
30
+ return false;
31
+ }
32
+ return true;
33
+ }
34
+ /** Clean up expired sessions (called periodically). */
35
+ export function cleanupNavSessions() {
36
+ const now = Date.now();
37
+ for (const [id, exp] of navSessions) {
38
+ if (now > exp)
39
+ navSessions.delete(id);
40
+ }
41
+ }
42
+ /** Build the Set-Cookie header value for a nav session. */
43
+ export function buildNavSessionCookie(sessionId) {
44
+ const maxAge = Math.floor(NAV_SESSION_TTL_MS / 1000);
45
+ return `nav_session=${sessionId}; HttpOnly; Secure; SameSite=Strict; Path=/nav/; Max-Age=${maxAge}`;
46
+ }
47
+ /** Extract nav_session value from a Cookie header. */
48
+ export function parseNavSessionCookie(cookieHeader) {
49
+ if (!cookieHeader)
50
+ return null;
51
+ const match = cookieHeader.match(/(?:^|;\s*)nav_session=([a-f0-9-]{36})/);
52
+ return match ? match[1] : null;
53
+ }
54
+ /**
55
+ * Generate a signed URL token for a nav path.
56
+ * Token = HMAC-SHA256(secret, path + "|" + expiry)
57
+ */
58
+ export function generateNavToken(secret, navPath, ttlMs = DEFAULT_NAV_TTL_MS) {
59
+ const exp = Date.now() + ttlMs;
60
+ const data = `${navPath}|${exp}`;
61
+ const token = crypto.createHmac("sha256", secret).update(data).digest("hex");
62
+ return { token, exp };
63
+ }
64
+ /**
65
+ * Verify a signed URL token. Returns true if valid and not expired.
66
+ */
67
+ export function verifyNavToken(secret, navPath, token, exp) {
68
+ if (Date.now() > exp)
69
+ return false;
70
+ const data = `${navPath}|${exp}`;
71
+ const expected = crypto.createHmac("sha256", secret).update(data).digest("hex");
72
+ return crypto.timingSafeEqual(Buffer.from(token), Buffer.from(expected));
73
+ }
74
+ /**
75
+ * Build a full nav URL with signed token query params.
76
+ * Used only for entry URLs sent via LINE messages.
77
+ */
78
+ export function buildSignedNavUrl(baseUrl, routePath, secret, ttlMs) {
79
+ const { token, exp } = generateNavToken(secret, routePath, ttlMs);
80
+ return `${baseUrl}${routePath}?token=${token}&exp=${exp}`;
81
+ }
82
+ /**
83
+ * Build a plain nav URL without tokens (for internal links in rendered pages).
84
+ * Browser session cookie provides auth for subsequent navigations.
85
+ */
86
+ export function buildPlainNavUrl(baseUrl, routePath) {
87
+ return `${baseUrl}${routePath}`;
88
+ }
89
+ // ─── Path Validation ────────────────────────────────────────────────────────
90
+ /** File extensions renderable by /nav/view/ */
91
+ export const VIEWABLE_EXTENSIONS = new Set([
92
+ ".ts", ".js", ".tsx", ".jsx", ".mjs", ".cjs",
93
+ ".md", ".mdx",
94
+ ".json", ".jsonc",
95
+ ".py",
96
+ ".txt", ".log",
97
+ ".yaml", ".yml",
98
+ ".html", ".htm", ".css", ".scss",
99
+ ".sh", ".bash", ".zsh", ".fish",
100
+ ".toml", ".ini", ".cfg",
101
+ ".xml", ".svg",
102
+ ".sql",
103
+ ".env", ".env.local", ".env.example",
104
+ ".gitignore", ".dockerignore",
105
+ ".rs", ".go", ".java", ".kt", ".swift", ".c", ".cpp", ".h",
106
+ ".rb", ".php", ".lua", ".r", ".jl",
107
+ ".tf", ".hcl",
108
+ ".graphql", ".gql",
109
+ ".proto",
110
+ ".csv",
111
+ ]);
112
+ /** Directories excluded from /nav/ls/ listings */
113
+ const EXCLUDED_DIRS = new Set([
114
+ ".git", ".hg", ".svn",
115
+ "node_modules", "__pycache__", ".cache",
116
+ ".DS_Store",
117
+ ]);
118
+ /** Files excluded from /nav/ls/ listings (secrets, credentials) */
119
+ const EXCLUDED_PATTERNS = [
120
+ /^\.env(\.|$)/, // .env, .env.local, .env.production, etc.
121
+ /\.(pem|key|p12|pfx|jks|keystore)$/i,
122
+ /^id_rsa/,
123
+ /\.secret$/i,
124
+ /^credentials\.json$/i,
125
+ ];
126
+ /** Check if a filename matches any exclusion pattern */
127
+ function isExcludedFile(name) {
128
+ return EXCLUDED_PATTERNS.some(p => p.test(name));
129
+ }
130
+ /** Max file size for rendering (200KB source) */
131
+ const MAX_VIEW_SIZE = 200 * 1024;
132
+ /** Check first 8KB for null bytes to detect binary files */
133
+ function isBinaryFile(filePath) {
134
+ const fd = fs.openSync(filePath, "r");
135
+ try {
136
+ const buf = Buffer.alloc(8192);
137
+ const bytesRead = fs.readSync(fd, buf, 0, 8192, 0);
138
+ for (let i = 0; i < bytesRead; i++) {
139
+ if (buf[i] === 0)
140
+ return true;
141
+ }
142
+ return false;
143
+ }
144
+ finally {
145
+ fs.closeSync(fd);
146
+ }
147
+ }
148
+ /** Max directory entries */
149
+ const MAX_DIR_ENTRIES = 100;
150
+ /**
151
+ * Validate and resolve a nav path against the workspace root.
152
+ * Returns the resolved absolute path or an error string.
153
+ */
154
+ export function resolveNavPath(workspacePath, navPath) {
155
+ // Reject null bytes
156
+ if (navPath.includes("\0")) {
157
+ return { error: "Invalid path", status: 400 };
158
+ }
159
+ // Normalize and resolve
160
+ const cleaned = path.normalize(navPath);
161
+ const resolved = path.resolve(workspacePath, cleaned);
162
+ // Must be within workspace
163
+ if (!resolved.startsWith(workspacePath + path.sep) && resolved !== workspacePath) {
164
+ return { error: "Path outside workspace", status: 403 };
165
+ }
166
+ // Check for symlink escapes
167
+ try {
168
+ const real = fs.realpathSync(resolved);
169
+ if (!real.startsWith(workspacePath + path.sep) && real !== workspacePath) {
170
+ return { error: "Path outside workspace", status: 403 };
171
+ }
172
+ }
173
+ catch {
174
+ // File doesn't exist
175
+ return { error: "Not found", status: 404 };
176
+ }
177
+ return { resolved };
178
+ }
179
+ // ─── HTML Rendering ─────────────────────────────────────────────────────────
180
+ function escapeHtml(text) {
181
+ return text
182
+ .replace(/&/g, "&amp;")
183
+ .replace(/</g, "&lt;")
184
+ .replace(/>/g, "&gt;")
185
+ .replace(/"/g, "&quot;");
186
+ }
187
+ /** Map file extensions to highlight.js language names */
188
+ function langFromExt(ext) {
189
+ const map = {
190
+ ".ts": "typescript", ".tsx": "typescript",
191
+ ".js": "javascript", ".jsx": "javascript", ".mjs": "javascript", ".cjs": "javascript",
192
+ ".py": "python",
193
+ ".json": "json", ".jsonc": "json",
194
+ ".yaml": "yaml", ".yml": "yaml",
195
+ ".html": "html", ".htm": "html",
196
+ ".css": "css", ".scss": "scss",
197
+ ".sh": "bash", ".bash": "bash", ".zsh": "bash", ".fish": "bash",
198
+ ".sql": "sql",
199
+ ".xml": "xml", ".svg": "xml",
200
+ ".toml": "toml", ".ini": "ini",
201
+ ".rs": "rust", ".go": "go", ".java": "java", ".kt": "kotlin",
202
+ ".swift": "swift", ".c": "c", ".cpp": "cpp", ".h": "c",
203
+ ".rb": "ruby", ".php": "php", ".lua": "lua", ".r": "r",
204
+ ".graphql": "graphql", ".gql": "graphql",
205
+ ".proto": "protobuf",
206
+ ".tf": "hcl", ".hcl": "hcl",
207
+ ".csv": "plaintext",
208
+ };
209
+ return map[ext] || "plaintext";
210
+ }
211
+ /** Shared CSS for all nav pages */
212
+ const NAV_CSS = `
213
+ * { box-sizing: border-box; }
214
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; max-width: 900px; margin: 0 auto; padding: 16px; color: #333; background: #fff; }
215
+ .breadcrumbs { font-size: 0.85em; padding: 8px 12px; background: #f5f7fa; border-radius: 6px; margin-bottom: 16px; overflow-x: auto; white-space: nowrap; }
216
+ .breadcrumbs a { color: #0969da; text-decoration: none; }
217
+ .breadcrumbs a:hover { text-decoration: underline; }
218
+ .breadcrumbs .sep { color: #888; margin: 0 4px; }
219
+ .breadcrumbs .current { color: #333; font-weight: 600; }
220
+ pre { background: #f5f5f5; padding: 12px; border-radius: 6px; overflow-x: auto; font-size: 0.85em; line-height: 1.5; }
221
+ code { font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; }
222
+ pre code { background: none; padding: 0; }
223
+ .dir-list { list-style: none; padding: 0; margin: 0; }
224
+ .dir-list li { border-bottom: 1px solid #f0f0f0; }
225
+ .dir-list li:last-child { border-bottom: none; }
226
+ .dir-list a { display: block; padding: 10px 12px; color: #333; text-decoration: none; font-size: 0.95em; }
227
+ .dir-list a:hover { background: #f5f7fa; }
228
+ .dir-list .icon { margin-right: 8px; }
229
+ .dir-list .size { float: right; color: #888; font-size: 0.85em; }
230
+ .readme-section { margin-top: 24px; padding-top: 16px; border-top: 2px solid #e8e8e8; }
231
+ .readme-section h3 { font-size: 0.85em; color: #888; margin-bottom: 12px; }
232
+ .truncated { padding: 12px; background: #fff3e0; border-radius: 6px; color: #e65100; font-size: 0.85em; margin-top: 12px; }
233
+ table { border-collapse: collapse; width: 100%; margin: 1em 0; }
234
+ th, td { border: 1px solid #ddd; padding: 8px; text-align: left; white-space: nowrap; }
235
+ th { background: #f5f5f5; }
236
+ .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 1em 0; }
237
+ .table-wrap table { margin: 0; }
238
+ img { max-width: 100%; }
239
+ blockquote { border-left: 4px solid #ddd; margin: 0; padding: 0 1em; color: #666; }
240
+ .mermaid { text-align: center; margin: 1em 0; }
241
+ h1, h2, h3 { margin-top: 1.5em; }
242
+
243
+ `;
244
+ function wrapNavPage(opts) {
245
+ const cdnStyles = [];
246
+ const cdnScripts = [];
247
+ if (opts.hasCode) {
248
+ cdnStyles.push('<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github.min.css">');
249
+ cdnScripts.push('<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>', `<script>document.querySelectorAll('pre code${opts.hasMermaid ? ":not(.language-mermaid)" : ""}').forEach(el => hljs.highlightElement(el));</script>`);
250
+ }
251
+ if (opts.hasMermaid) {
252
+ cdnScripts.push(`<script type="module">
253
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
254
+ mermaid.initialize({ startOnLoad: false, theme: 'default' });
255
+ document.querySelectorAll('pre > code.language-mermaid').forEach(el => {
256
+ const pre = el.parentElement;
257
+ const div = document.createElement('div');
258
+ div.className = 'mermaid';
259
+ div.textContent = el.textContent;
260
+ pre.replaceWith(div);
261
+ });
262
+ await mermaid.run();
263
+ </script>`);
264
+ }
265
+ if (opts.hasMath) {
266
+ cdnStyles.push('<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.css">');
267
+ cdnScripts.push('<script src="https://cdn.jsdelivr.net/npm/katex@0.16/dist/katex.min.js"></script>', '<script src="https://cdn.jsdelivr.net/npm/katex@0.16/dist/contrib/auto-render.min.js"></script>', `<script>renderMathInElement(document.body, {delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}]});</script>`);
268
+ }
269
+ const cspSources = ["'self'", "cdn.jsdelivr.net"];
270
+ return `<!DOCTYPE html>
271
+ <html lang="en">
272
+ <head>
273
+ <meta charset="utf-8">
274
+ <meta name="viewport" content="width=device-width, initial-scale=1">
275
+ <meta name="referrer" content="no-referrer">
276
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src ${cspSources.join(" ")} 'unsafe-inline'; style-src ${cspSources.join(" ")} 'unsafe-inline'; img-src * data:; font-src ${cspSources.join(" ")}; connect-src 'none';">
277
+ <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
278
+ <title>${escapeHtml(opts.title)}</title>
279
+ <style>${NAV_CSS}</style>
280
+ ${cdnStyles.join("\n")}
281
+ </head>
282
+ <body>
283
+ ${opts.breadcrumbsHtml}
284
+ ${opts.bodyHtml}
285
+ ${cdnScripts.join("\n")}
286
+ </body>
287
+ </html>`;
288
+ }
289
+ function buildBreadcrumbs(opts) {
290
+ const parts = opts.navPath.split("/").filter(Boolean);
291
+ const crumbs = [];
292
+ // Root link
293
+ const rootUrl = buildPlainNavUrl(opts.baseUrl, "/nav/ls/");
294
+ crumbs.push(`<a href="${escapeHtml(rootUrl)}">📁 root</a>`);
295
+ // Directory segments
296
+ for (let i = 0; i < parts.length; i++) {
297
+ const isLast = i === parts.length - 1;
298
+ const segmentPath = parts.slice(0, i + 1).join("/");
299
+ if (isLast && opts.isFile) {
300
+ crumbs.push(`<span class="current">${escapeHtml(parts[i])}</span>`);
301
+ }
302
+ else if (isLast) {
303
+ crumbs.push(`<span class="current">📁 ${escapeHtml(parts[i])}</span>`);
304
+ }
305
+ else {
306
+ const url = buildPlainNavUrl(opts.baseUrl, `/nav/ls/${segmentPath}`);
307
+ crumbs.push(`<a href="${escapeHtml(url)}">📁 ${escapeHtml(parts[i])}</a>`);
308
+ }
309
+ }
310
+ return `<nav class="breadcrumbs">${crumbs.join('<span class="sep">/</span>')}</nav>`;
311
+ }
312
+ /**
313
+ * Render a file for /nav/view/<path>.
314
+ */
315
+ export async function renderNavView(workspacePath, navPath, baseUrl) {
316
+ const result = resolveNavPath(workspacePath, navPath);
317
+ if ("error" in result) {
318
+ return { html: errorPage(result.error), status: result.status };
319
+ }
320
+ const { resolved } = result;
321
+ // Must be a file
322
+ let stat;
323
+ try {
324
+ stat = fs.statSync(resolved);
325
+ }
326
+ catch {
327
+ return { html: errorPage("Not found"), status: 404 };
328
+ }
329
+ if (stat.isDirectory()) {
330
+ // Redirect: /nav/view/dir → /nav/ls/dir
331
+ return { html: "", status: 301 };
332
+ }
333
+ if (!stat.isFile()) {
334
+ return { html: errorPage("Not a regular file"), status: 400 };
335
+ }
336
+ const ext = path.extname(resolved).toLowerCase();
337
+ // Reject secret files
338
+ if (isExcludedFile(path.basename(resolved))) {
339
+ return { html: errorPage("File not accessible"), status: 403 };
340
+ }
341
+ // Image files: render inline via /nav/raw/
342
+ const IMAGE_EXTS = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".ico"]);
343
+ if (IMAGE_EXTS.has(ext)) {
344
+ if (stat.size > 5 * 1024 * 1024) {
345
+ return { html: errorPage("Image too large (>5MB)"), status: 413 };
346
+ }
347
+ const breadcrumbsHtml = buildBreadcrumbs({ navPath, isFile: true, baseUrl });
348
+ const imgUrl = buildPlainNavUrl(baseUrl, `/nav/raw/${navPath}`);
349
+ const body = `<div style="text-align:center;"><img src="${escapeHtml(imgUrl)}" alt="${escapeHtml(path.basename(navPath))}" style="max-width:100%;border-radius:8px;"></div>`;
350
+ return {
351
+ html: wrapNavPage({ title: path.basename(navPath), breadcrumbsHtml, bodyHtml: body }),
352
+ status: 200,
353
+ };
354
+ }
355
+ // Reject binary files (check first 8KB for null bytes)
356
+ if (isBinaryFile(resolved)) {
357
+ return { html: errorPage("Binary file — not viewable"), status: 415 };
358
+ }
359
+ // Check size
360
+ let truncated = false;
361
+ let content;
362
+ if (stat.size > MAX_VIEW_SIZE) {
363
+ const buffer = Buffer.alloc(MAX_VIEW_SIZE);
364
+ const fd = fs.openSync(resolved, "r");
365
+ try {
366
+ fs.readSync(fd, buffer, 0, MAX_VIEW_SIZE, 0);
367
+ }
368
+ finally {
369
+ fs.closeSync(fd);
370
+ }
371
+ content = buffer.toString("utf-8");
372
+ truncated = true;
373
+ }
374
+ else {
375
+ content = fs.readFileSync(resolved, "utf-8");
376
+ }
377
+ const breadcrumbsHtml = buildBreadcrumbs({ navPath, isFile: true, baseUrl });
378
+ // Markdown files: render as HTML
379
+ if (ext === ".md" || ext === ".mdx") {
380
+ const rawHtml = await marked.parse(content);
381
+ const hasMermaid = /```mermaid/i.test(content);
382
+ const hasCode = /```\w+/i.test(content);
383
+ const hasMath = /\$\$[\s\S]+?\$\$|\$[^$\n]+?\$/m.test(content);
384
+ // Replace internal links with nav links
385
+ let bodyHtml = replaceInternalLinks(rawHtml, navPath, baseUrl);
386
+ // Wrap tables for horizontal scrolling on mobile
387
+ bodyHtml = bodyHtml.replace(/<table\b/g, '<div class="table-wrap"><table')
388
+ .replace(/<\/table>/g, '</table></div>');
389
+ let body = bodyHtml;
390
+ if (truncated) {
391
+ body += `\n<div class="truncated">⚠️ File truncated at ${(MAX_VIEW_SIZE / 1024).toFixed(0)}KB. Full file is ${(stat.size / 1024).toFixed(0)}KB.</div>`;
392
+ }
393
+ return {
394
+ html: wrapNavPage({
395
+ title: path.basename(navPath),
396
+ breadcrumbsHtml,
397
+ bodyHtml: body,
398
+ hasCode,
399
+ hasMermaid,
400
+ hasMath,
401
+ }),
402
+ status: 200,
403
+ };
404
+ }
405
+ // Code files: syntax highlighted
406
+ const lang = langFromExt(ext);
407
+ let body = `<pre><code class="language-${lang}">${escapeHtml(content)}</code></pre>`;
408
+ if (truncated) {
409
+ body += `\n<div class="truncated">⚠️ File truncated at ${(MAX_VIEW_SIZE / 1024).toFixed(0)}KB. Full file is ${(stat.size / 1024).toFixed(0)}KB.</div>`;
410
+ }
411
+ return {
412
+ html: wrapNavPage({
413
+ title: path.basename(navPath),
414
+ breadcrumbsHtml,
415
+ bodyHtml: body,
416
+ hasCode: true,
417
+ }),
418
+ status: 200,
419
+ };
420
+ }
421
+ // ─── List Handler ───────────────────────────────────────────────────────────
422
+ /**
423
+ * Render a directory listing for /nav/ls/<path>.
424
+ */
425
+ export async function renderNavList(workspacePath, navPath, baseUrl) {
426
+ const dirToList = navPath || ".";
427
+ const result = resolveNavPath(workspacePath, dirToList);
428
+ if ("error" in result) {
429
+ return { html: errorPage(result.error), status: result.status };
430
+ }
431
+ const { resolved } = result;
432
+ let stat;
433
+ try {
434
+ stat = fs.statSync(resolved);
435
+ }
436
+ catch {
437
+ return { html: errorPage("Not found"), status: 404 };
438
+ }
439
+ if (!stat.isDirectory()) {
440
+ return { html: "", status: 301 }; // redirect to /nav/view/
441
+ }
442
+ let entries;
443
+ try {
444
+ entries = fs.readdirSync(resolved, { withFileTypes: true });
445
+ }
446
+ catch {
447
+ return { html: errorPage("Cannot read directory"), status: 500 };
448
+ }
449
+ // Filter and sort
450
+ const filtered = entries.filter(e => {
451
+ if (EXCLUDED_DIRS.has(e.name))
452
+ return false;
453
+ if (isExcludedFile(e.name))
454
+ return false;
455
+ return true;
456
+ });
457
+ const dirs = filtered.filter(e => e.isDirectory()).sort((a, b) => a.name.localeCompare(b.name));
458
+ const files = filtered.filter(e => e.isFile()).sort((a, b) => a.name.localeCompare(b.name));
459
+ const sorted = [...dirs, ...files].slice(0, MAX_DIR_ENTRIES);
460
+ const breadcrumbsHtml = buildBreadcrumbs({ navPath: navPath || "", isFile: false, baseUrl });
461
+ // Build list HTML
462
+ const listItems = sorted.map(entry => {
463
+ const entryPath = navPath ? `${navPath}/${entry.name}` : entry.name;
464
+ const isDir = entry.isDirectory();
465
+ const route = isDir ? `/nav/ls/${entryPath}` : `/nav/view/${entryPath}`;
466
+ const url = buildPlainNavUrl(baseUrl, route);
467
+ const icon = isDir ? "📁" : "📄";
468
+ let sizeHtml = "";
469
+ if (!isDir) {
470
+ try {
471
+ const fileStat = fs.statSync(path.join(resolved, entry.name));
472
+ sizeHtml = `<span class="size">${formatSize(fileStat.size)}</span>`;
473
+ }
474
+ catch { /* ignore */ }
475
+ }
476
+ return `<li><a href="${escapeHtml(url)}"><span class="icon">${icon}</span>${escapeHtml(entry.name)}${sizeHtml}</a></li>`;
477
+ }).join("\n");
478
+ let bodyHtml = `<ul class="dir-list">\n${listItems}\n</ul>`;
479
+ if (filtered.length > MAX_DIR_ENTRIES) {
480
+ bodyHtml += `\n<div class="truncated">⚠️ Showing first ${MAX_DIR_ENTRIES} of ${filtered.length} entries.</div>`;
481
+ }
482
+ // README auto-append (D5)
483
+ const readmeResult = await renderReadmeIfPresent(resolved, navPath, baseUrl);
484
+ if (readmeResult) {
485
+ bodyHtml += readmeResult;
486
+ }
487
+ return {
488
+ html: wrapNavPage({
489
+ title: navPath ? path.basename(navPath) : "root",
490
+ breadcrumbsHtml,
491
+ bodyHtml,
492
+ hasMermaid: readmeResult?.includes("language-mermaid") ?? false,
493
+ hasCode: readmeResult != null,
494
+ hasMath: false,
495
+ }),
496
+ status: 200,
497
+ };
498
+ }
499
+ // ─── README Auto-Append ─────────────────────────────────────────────────────
500
+ async function renderReadmeIfPresent(dirPath, navPath, baseUrl) {
501
+ const candidates = ["README.md", "readme.md", "Readme.md", "index.md", "INDEX.md"];
502
+ let readmeName = null;
503
+ for (const name of candidates) {
504
+ const fullPath = path.join(dirPath, name);
505
+ if (fs.existsSync(fullPath)) {
506
+ readmeName = name;
507
+ break;
508
+ }
509
+ }
510
+ if (!readmeName)
511
+ return null;
512
+ try {
513
+ const content = fs.readFileSync(path.join(dirPath, readmeName), "utf-8");
514
+ // Limit readme rendering to 50KB
515
+ const trimmed = content.length > 50000 ? content.slice(0, 50000) : content;
516
+ const rawHtml = await marked.parse(trimmed);
517
+ const readmePath = navPath ? `${navPath}/${readmeName}` : readmeName;
518
+ let bodyHtml = replaceInternalLinks(rawHtml, readmePath, baseUrl);
519
+ bodyHtml = bodyHtml.replace(/<table\b/g, '<div class="table-wrap"><table')
520
+ .replace(/<\/table>/g, '</table></div>');
521
+ return `\n<div class="readme-section">
522
+ <h3>📖 ${escapeHtml(readmeName)}</h3>
523
+ ${bodyHtml}
524
+ </div>`;
525
+ }
526
+ catch {
527
+ return null;
528
+ }
529
+ }
530
+ // ─── Internal Link Replacement ──────────────────────────────────────────────
531
+ /**
532
+ * Replace relative links in rendered HTML with signed /nav/ URLs.
533
+ */
534
+ function replaceInternalLinks(html, currentNavPath, baseUrl) {
535
+ const dirPath = path.dirname(currentNavPath);
536
+ // Replace relative <a href="..."> with signed nav URLs
537
+ let result = html.replace(/<a\b([^>]*?)href="([^"]+)"([^>]*)>/gi, (_match, pre, href, post) => {
538
+ const trimmed = href.trim();
539
+ // Only transform relative links
540
+ if (!trimmed.startsWith("./") && !trimmed.startsWith("../") && !trimmed.startsWith("#") && !trimmed.match(/^[a-zA-Z][\w-]*\.[a-zA-Z]+$/)) {
541
+ return `<a${pre}href="${escapeHtml(href)}"${post}>`;
542
+ }
543
+ // Skip anchor links
544
+ if (trimmed.startsWith("#")) {
545
+ return `<a${pre}href="${escapeHtml(href)}"${post}>`;
546
+ }
547
+ // Resolve relative path
548
+ const targetPath = path.normalize(path.join(dirPath, trimmed));
549
+ // Determine if target is a directory or file
550
+ const isDir = trimmed.endsWith("/") || !path.extname(trimmed);
551
+ const route = isDir ? `/nav/ls/${targetPath}` : `/nav/view/${targetPath}`;
552
+ const url = buildPlainNavUrl(baseUrl, route);
553
+ return `<a${pre}href="${escapeHtml(url)}"${post}>`;
554
+ });
555
+ // Replace relative <img src="..."> with signed /nav/raw/ URLs
556
+ result = result.replace(/<img\b([^>]*?)src="([^"]+)"([^>]*?)>/gi, (_match, pre, src, post) => {
557
+ const trimmed = src.trim();
558
+ // Only transform relative paths (skip absolute URLs and data URIs)
559
+ if (trimmed.startsWith("http://") || trimmed.startsWith("https://") ||
560
+ trimmed.startsWith("data:") || trimmed.startsWith("//")) {
561
+ return `<img${pre}src="${escapeHtml(src)}"${post}>`;
562
+ }
563
+ // Resolve relative path
564
+ const targetPath = path.normalize(path.join(dirPath, trimmed));
565
+ if (targetPath.startsWith("..")) {
566
+ return `<img${pre}src="${escapeHtml(src)}"${post}>`;
567
+ }
568
+ const url = buildPlainNavUrl(baseUrl, `/nav/raw/${targetPath}`);
569
+ return `<img${pre}src="${escapeHtml(url)}"${post}>`;
570
+ });
571
+ return result;
572
+ }
573
+ // ─── Raw File Serving ───────────────────────────────────────────────────────
574
+ const MIME_TYPES = {
575
+ ".svg": "image/svg+xml",
576
+ ".png": "image/png",
577
+ ".jpg": "image/jpeg",
578
+ ".jpeg": "image/jpeg",
579
+ ".gif": "image/gif",
580
+ ".webp": "image/webp",
581
+ ".ico": "image/x-icon",
582
+ ".css": "text/css",
583
+ ".js": "text/javascript",
584
+ ".json": "application/json",
585
+ ".woff": "font/woff",
586
+ ".woff2": "font/woff2",
587
+ ".ttf": "font/ttf",
588
+ };
589
+ /**
590
+ * Serve a raw file from the workspace with correct Content-Type.
591
+ * Used for images/assets referenced in markdown.
592
+ */
593
+ export function renderNavRaw(navPath, workspacePath) {
594
+ const pathResult = resolveNavPath(workspacePath, navPath);
595
+ if ("error" in pathResult) {
596
+ return pathResult;
597
+ }
598
+ const resolved = pathResult.resolved;
599
+ if (!fs.statSync(resolved).isFile()) {
600
+ return { error: "Not found", status: 404 };
601
+ }
602
+ const ext = path.extname(resolved).toLowerCase();
603
+ const contentType = MIME_TYPES[ext] || "application/octet-stream";
604
+ // Size limit for raw files: 5MB
605
+ const stat = fs.statSync(resolved);
606
+ if (stat.size > 5 * 1024 * 1024) {
607
+ return { error: "File too large", status: 413 };
608
+ }
609
+ return { data: fs.readFileSync(resolved), contentType, status: 200 };
610
+ }
611
+ function formatSize(bytes) {
612
+ if (bytes < 1024)
613
+ return `${bytes}B`;
614
+ if (bytes < 1024 * 1024)
615
+ return `${(bytes / 1024).toFixed(1)}KB`;
616
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
617
+ }
618
+ function errorPage(message) {
619
+ return `<!DOCTYPE html>
620
+ <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
621
+ <title>Error</title>
622
+ <style>body { font-family: -apple-system, sans-serif; display: flex; align-items: center; justify-content: center; min-height: 80vh; color: #666; } .err { text-align: center; } .err h1 { font-size: 1.5em; color: #c62828; }</style>
623
+ </head><body><div class="err"><h1>⚠️ ${escapeHtml(message)}</h1></div></body></html>`;
624
+ }
625
+ //# sourceMappingURL=navBrowser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navBrowser.js","sourceRoot":"","sources":["../../src/tools/navBrowser.ts"],"names":[],"mappings":"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"}