repoview 0.5.1 → 0.6.1

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 (57) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/CONTRIBUTING.md +4 -3
  3. package/DEVELOPMENT.md +84 -16
  4. package/README.md +71 -5
  5. package/dist/api.js +58 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli.js +454 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/csv.js +64 -0
  10. package/dist/csv.js.map +1 -0
  11. package/dist/format.js +25 -0
  12. package/dist/format.js.map +1 -0
  13. package/dist/gist-router.js +153 -0
  14. package/dist/gist-router.js.map +1 -0
  15. package/dist/gists.js +130 -0
  16. package/dist/gists.js.map +1 -0
  17. package/dist/git.js +67 -0
  18. package/dist/git.js.map +1 -0
  19. package/dist/gitignore.js +34 -0
  20. package/dist/gitignore.js.map +1 -0
  21. package/dist/linkcheck.js +310 -0
  22. package/dist/linkcheck.js.map +1 -0
  23. package/dist/markdown.js +493 -0
  24. package/dist/markdown.js.map +1 -0
  25. package/dist/net.js +10 -0
  26. package/dist/net.js.map +1 -0
  27. package/dist/paths.js +59 -0
  28. package/dist/paths.js.map +1 -0
  29. package/dist/reload.js +55 -0
  30. package/dist/reload.js.map +1 -0
  31. package/dist/repo-context.js +80 -0
  32. package/dist/repo-context.js.map +1 -0
  33. package/dist/repo-router.js +810 -0
  34. package/dist/repo-router.js.map +1 -0
  35. package/dist/review-cli.js +228 -0
  36. package/dist/review-cli.js.map +1 -0
  37. package/dist/server.js +122 -0
  38. package/dist/server.js.map +1 -0
  39. package/dist/session.js +86 -0
  40. package/dist/session.js.map +1 -0
  41. package/dist/types.js +2 -0
  42. package/dist/types.js.map +1 -0
  43. package/dist/views.js +780 -0
  44. package/dist/views.js.map +1 -0
  45. package/package.json +20 -9
  46. package/public/app.css +113 -0
  47. package/public/app.js +26 -3
  48. package/public/gist.js +60 -0
  49. package/public/review.js +9 -6
  50. package/public/session.js +61 -0
  51. package/src/cli.js +0 -91
  52. package/src/gitignore.js +0 -34
  53. package/src/linkcheck.js +0 -312
  54. package/src/markdown.js +0 -518
  55. package/src/review-cli.js +0 -245
  56. package/src/server.js +0 -1126
  57. package/src/views.js +0 -657
package/dist/cli.js ADDED
@@ -0,0 +1,454 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import { startServer } from "./server.js";
5
+ import { handleReviewCommand } from "./review-cli.js";
6
+ function printHelp() {
7
+ // Keep this in sync with README.md
8
+ process.stdout.write(`repoview — browse local Git repos as a GitHub-like website, and publish
9
+ ephemeral file previews ("gists"). Built to be driven by humans and agents.
10
+
11
+ SESSION MODEL (like tmux)
12
+ Invocations on the same port share ONE session (daemon). The FIRST run starts
13
+ the daemon and KEEPS RUNNING in the foreground (it is the server). LATER runs
14
+ on that port just register their repo and exit 0 immediately. So you never have
15
+ to remember a port per repo. Each repo is served at /r/<id>/...
16
+ Default port: 7376. Use --port for independent sessions.
17
+ Agent tip: background the first run (e.g. \`repoview … &\` or nohup); once it
18
+ prints "listening:", the daemon is up and all other commands below will work.
19
+
20
+ START / JOIN A SESSION
21
+ repoview [--repo PATH] [--host HOST] [--port N] [--no-watch]
22
+ If no daemon is on --port: becomes the daemon (blocks/foreground).
23
+ If a daemon is already there: registers the repo, prints its URL, exits 0.
24
+
25
+ Options:
26
+ --repo <path> Repo root (default: $REPO_ROOT or current dir)
27
+ --host <host> Bind address (default: 0.0.0.0; use 127.0.0.1 for local-only)
28
+ --port <port> Session port (default: 7376)
29
+ --no-watch Disable live reload for this repo
30
+ -h, --help Show this help
31
+
32
+ MANAGE THE SESSION (require a running daemon on --port)
33
+ repoview ls List repos: "<id> <branch> <path>" + each URL
34
+ repoview rm <id|path> Unregister a repo
35
+ repoview stop Shut the session daemon down
36
+
37
+ GISTS (ephemeral file previews; default TTL 24h, gone on restart, editable)
38
+ Need a running daemon on --port (or --url for a remote server's API).
39
+ repoview gist <file> [--title "T"] [--ttl 24h] [--filename name.md] [--url URL]
40
+ Publish; prints ONE line: the URL.
41
+ cat report.md | repoview gist --filename report.md Publish from stdin
42
+ repoview gist edit <id> [file] [--title] [--filename] [--ttl] Update a gist
43
+ repoview gist delete <id> Delete a gist
44
+ repoview gist list List gists
45
+ --ttl accepts 30m/24h/7d/seconds (1m–7d). --title is the page/list label
46
+ only; the rendered H1 comes from the file's own first Markdown heading.
47
+
48
+ CODE REVIEW THREADS (pure filesystem, NO daemon — operate on a repo's .repoview/)
49
+ Add --repo <path> to EVERY review command (default: $REPO_ROOT or cwd — NOT the
50
+ session's served repo). --port/--host are ignored here.
51
+ repoview review new --repo R --title "Title" Create (prints id)
52
+ repoview review post --repo R <id> --role agent --body "…" Post a message
53
+ repoview review post --repo R <id> --role agent --file F Post from file/stdin
54
+ repoview review read --repo R <id> Print thread JSON
55
+ repoview review list --repo R List threads (JSON)
56
+
57
+ HTTP API (for agents / remote use — base = http://<host>:<port>)
58
+ GET /api/session {app, version, repos:[{id,name,path,branch}]}
59
+ GET /api/repos {repos:[…]}
60
+ POST /api/repos {path, watch?} → {id, url} (localhost only)
61
+ DELETE /api/repos/:id → {ok} (localhost only)
62
+ POST /api/shutdown → {ok} (localhost only)
63
+ GET /api/gists {gists:[{id,filename,title,url,expiresAt}]}
64
+ POST /api/gists {content, filename?, title?, ttlSeconds?}
65
+ → {id, url, rawUrl, expiresAt}
66
+ PATCH /api/gists/:id {content?, filename?, title?, ttlSeconds?} → gist
67
+ DELETE /api/gists/:id → {ok}
68
+ Examples:
69
+ curl -s $BASE/api/session
70
+ curl -s -X POST $BASE/api/gists -H 'content-type: application/json' \\
71
+ -d '{"content":"# Hi","filename":"hi.md","ttlSeconds":3600}'
72
+
73
+ PAGES
74
+ / → default repo /session manage repos (add/remove)
75
+ /r/<id>/tree/ browse a repo /gists list of active gists
76
+ /r/<id>/diff working-tree diff /gist/<id> a gist preview (+ /raw)
77
+ /r/<id>/review/ review threads
78
+
79
+ ENVIRONMENT
80
+ REPO_ROOT Default repo when --repo is omitted
81
+ HOST, PORT Default bind host / session port
82
+ REPOVIEW_BASE_URL Absolute origin used in returned gist URLs. Read by the
83
+ SERVER/daemon at request time — set it when STARTING the
84
+ daemon, not on the gist client. Falls back to the request
85
+ Host header. (e.g. when the server runs remotely)
86
+ `);
87
+ }
88
+ function parseArgs(argv) {
89
+ const args = { watch: true };
90
+ const rest = [];
91
+ for (let i = 0; i < argv.length; i++) {
92
+ const value = argv[i];
93
+ if (value === "-h" || value === "--help")
94
+ args.help = true;
95
+ if (value === "--watch")
96
+ args.watch = true;
97
+ else if (value === "--no-watch")
98
+ args.watch = false;
99
+ else if (value === "--repo")
100
+ args.repo = argv[++i];
101
+ else if (value === "--port")
102
+ args.port = Number(argv[++i]);
103
+ else if (value === "--host")
104
+ args.host = argv[++i];
105
+ else
106
+ rest.push(value);
107
+ }
108
+ return { ...args, rest };
109
+ }
110
+ /** Address to connect to when joining a local daemon (0.0.0.0 isn't routable). */
111
+ function connectHost(host) {
112
+ if (host === "0.0.0.0" || host === "::" || host === "")
113
+ return "127.0.0.1";
114
+ return host;
115
+ }
116
+ async function fetchJson(url, init) {
117
+ try {
118
+ const res = await fetch(url, init);
119
+ if (!res.ok) {
120
+ const body = (await res.json().catch(() => ({})));
121
+ throw new Error(body.error || `HTTP ${res.status}`);
122
+ }
123
+ return await res.json();
124
+ }
125
+ catch (e) {
126
+ if (e instanceof Error && /HTTP \d|error/i.test(e.message) && !/fetch failed|ECONNREFUSED/i.test(e.message)) {
127
+ throw e;
128
+ }
129
+ return null;
130
+ }
131
+ }
132
+ async function probeSession(base) {
133
+ return (await fetchJson(`${base}/api/session`));
134
+ }
135
+ async function registerRepo(base, repoRoot, watch) {
136
+ const result = await fetchJson(`${base}/api/repos`, {
137
+ method: "POST",
138
+ headers: { "Content-Type": "application/json" },
139
+ body: JSON.stringify({ path: repoRoot, watch }),
140
+ });
141
+ if (!result)
142
+ throw new Error("Failed to register repo with the session");
143
+ return result;
144
+ }
145
+ function printRepoTable(repos, port, host) {
146
+ if (!repos.length) {
147
+ process.stdout.write("(no repos registered)\n");
148
+ return;
149
+ }
150
+ const open = connectHost(host);
151
+ for (const r of repos) {
152
+ process.stdout.write(`${r.id.padEnd(20)} ${(r.branch || "no-git").padEnd(16)} ${r.path}\n` +
153
+ `${" ".repeat(20)} http://${open}:${port}/r/${r.id}/tree/\n`);
154
+ }
155
+ }
156
+ async function runSubcommand(sub, args, base, port, host) {
157
+ if (sub === "ls") {
158
+ const info = await probeSession(base);
159
+ if (!info) {
160
+ process.stderr.write(`No repoview session on ${base}\n`);
161
+ return 1;
162
+ }
163
+ printRepoTable(info.repos || [], port, host);
164
+ return 0;
165
+ }
166
+ if (sub === "stop") {
167
+ const info = await probeSession(base);
168
+ if (!info) {
169
+ process.stderr.write(`No repoview session on ${base}\n`);
170
+ return 1;
171
+ }
172
+ await fetchJson(`${base}/api/shutdown`, { method: "POST" });
173
+ process.stdout.write(`Stopped session on port ${port}\n`);
174
+ return 0;
175
+ }
176
+ if (sub === "rm") {
177
+ const target = args.rest[1];
178
+ if (!target) {
179
+ process.stderr.write("Usage: repoview rm <id|path>\n");
180
+ return 1;
181
+ }
182
+ const info = await probeSession(base);
183
+ if (!info) {
184
+ process.stderr.write(`No repoview session on ${base}\n`);
185
+ return 1;
186
+ }
187
+ const repos = info.repos || [];
188
+ let real = target;
189
+ try {
190
+ real = path.resolve(target);
191
+ }
192
+ catch {
193
+ // keep as-is
194
+ }
195
+ const match = repos.find((r) => r.id === target || r.path === real || r.path === target);
196
+ if (!match) {
197
+ process.stderr.write(`Repo not found in session: ${target}\n`);
198
+ return 1;
199
+ }
200
+ const res = await fetchJson(`${base}/api/repos/${encodeURIComponent(match.id)}`, {
201
+ method: "DELETE",
202
+ });
203
+ if (!res) {
204
+ process.stderr.write(`Failed to remove ${match.id}\n`);
205
+ return 1;
206
+ }
207
+ process.stdout.write(`Removed ${match.id}\n`);
208
+ return 0;
209
+ }
210
+ process.stderr.write(`Unknown command: ${sub}\n`);
211
+ printHelp();
212
+ return 1;
213
+ }
214
+ /** Parse "24h" / "30m" / "7d" / "3600" into seconds. */
215
+ function parseDuration(text) {
216
+ const m = String(text).trim().match(/^(\d+)\s*([smhd]?)$/i);
217
+ if (!m)
218
+ return undefined;
219
+ const n = Number(m[1]);
220
+ const unit = m[2].toLowerCase();
221
+ const mult = unit === "d" ? 86400 : unit === "h" ? 3600 : unit === "m" ? 60 : 1;
222
+ return n * mult;
223
+ }
224
+ function parseGistArgs(args) {
225
+ const flags = {};
226
+ const positional = [];
227
+ for (let i = 0; i < args.length; i++) {
228
+ const v = args[i];
229
+ if (v === "--title")
230
+ flags.title = args[++i];
231
+ else if (v === "--ttl")
232
+ flags.ttl = args[++i];
233
+ else if (v === "--filename")
234
+ flags.filename = args[++i];
235
+ else if (v === "--url")
236
+ flags.url = args[++i];
237
+ else
238
+ positional.push(v);
239
+ }
240
+ return { flags, positional };
241
+ }
242
+ /** Read content from a file path, else stdin if piped, else undefined. */
243
+ async function readGistContent(file) {
244
+ if (file) {
245
+ const fs = await import("node:fs/promises");
246
+ return fs.readFile(file, "utf8");
247
+ }
248
+ if (!process.stdin.isTTY) {
249
+ const chunks = [];
250
+ for await (const chunk of process.stdin)
251
+ chunks.push(chunk);
252
+ return Buffer.concat(chunks).toString("utf8");
253
+ }
254
+ return undefined;
255
+ }
256
+ function ttlSecondsFrom(flags) {
257
+ if (!flags.ttl)
258
+ return undefined;
259
+ const s = parseDuration(flags.ttl);
260
+ if (s == null) {
261
+ process.stderr.write(`Invalid --ttl: ${flags.ttl} (use e.g. 30m, 24h, 7d)\n`);
262
+ return null; // signal error
263
+ }
264
+ return s;
265
+ }
266
+ function gistTarget(flags, localBase) {
267
+ return flags.url ? flags.url.replace(/\/+$/, "") : localBase;
268
+ }
269
+ function noSession(target) {
270
+ process.stderr.write(`No repoview session at ${target}. Start one with \`repoview\` first, or pass --url.\n`);
271
+ return 1;
272
+ }
273
+ async function runGist(restArgs, localBase) {
274
+ const sub = restArgs[0];
275
+ if (sub === "edit")
276
+ return runGistEdit(restArgs.slice(1), localBase);
277
+ if (sub === "delete" || sub === "rm")
278
+ return runGistDelete(restArgs.slice(1), localBase);
279
+ if (sub === "list" || sub === "ls")
280
+ return runGistList(restArgs.slice(1), localBase);
281
+ return runGistCreate(sub === "create" ? restArgs.slice(1) : restArgs, localBase);
282
+ }
283
+ async function runGistCreate(args, localBase) {
284
+ const { flags, positional } = parseGistArgs(args);
285
+ const file = positional[0];
286
+ const content = await readGistContent(file);
287
+ if (!content || !content.trim()) {
288
+ process.stderr.write("Error: no content (pass a file or pipe via stdin)\n");
289
+ return 1;
290
+ }
291
+ const ttlSeconds = ttlSecondsFrom(flags);
292
+ if (ttlSeconds === null)
293
+ return 1;
294
+ const filename = flags.filename || (file ? path.basename(file) : "gist.md");
295
+ const target = gistTarget(flags, localBase);
296
+ let result;
297
+ try {
298
+ result = (await fetchJson(`${target}/api/gists`, {
299
+ method: "POST",
300
+ headers: { "Content-Type": "application/json" },
301
+ body: JSON.stringify({ content, filename, title: flags.title, ttlSeconds }),
302
+ }));
303
+ }
304
+ catch (e) {
305
+ process.stderr.write(`Error: ${e.message}\n`);
306
+ return 1;
307
+ }
308
+ if (!result)
309
+ return noSession(target);
310
+ process.stdout.write(`${result.url}\n`);
311
+ return 0;
312
+ }
313
+ async function runGistEdit(args, localBase) {
314
+ const { flags, positional } = parseGistArgs(args);
315
+ const id = positional[0];
316
+ if (!id) {
317
+ process.stderr.write("Usage: repoview gist edit <id> [file] [--title] [--filename] [--ttl]\n");
318
+ return 1;
319
+ }
320
+ const content = await readGistContent(positional[1]);
321
+ const ttlSeconds = ttlSecondsFrom(flags);
322
+ if (ttlSeconds === null)
323
+ return 1;
324
+ const body = {};
325
+ if (content !== undefined)
326
+ body.content = content;
327
+ if (flags.filename !== undefined)
328
+ body.filename = flags.filename;
329
+ if (flags.title !== undefined)
330
+ body.title = flags.title;
331
+ if (ttlSeconds !== undefined)
332
+ body.ttlSeconds = ttlSeconds;
333
+ if (Object.keys(body).length === 0) {
334
+ process.stderr.write("Nothing to update (pass new content, --title, --filename, or --ttl)\n");
335
+ return 1;
336
+ }
337
+ const target = gistTarget(flags, localBase);
338
+ let result;
339
+ try {
340
+ result = (await fetchJson(`${target}/api/gists/${encodeURIComponent(id)}`, {
341
+ method: "PATCH",
342
+ headers: { "Content-Type": "application/json" },
343
+ body: JSON.stringify(body),
344
+ }));
345
+ }
346
+ catch (e) {
347
+ process.stderr.write(`Error: ${e.message}\n`);
348
+ return 1;
349
+ }
350
+ if (!result)
351
+ return noSession(target);
352
+ process.stdout.write(`${result.url}\n`);
353
+ return 0;
354
+ }
355
+ async function runGistDelete(args, localBase) {
356
+ const { flags, positional } = parseGistArgs(args);
357
+ const id = positional[0];
358
+ if (!id) {
359
+ process.stderr.write("Usage: repoview gist delete <id>\n");
360
+ return 1;
361
+ }
362
+ const target = gistTarget(flags, localBase);
363
+ try {
364
+ const result = await fetchJson(`${target}/api/gists/${encodeURIComponent(id)}`, {
365
+ method: "DELETE",
366
+ });
367
+ if (!result)
368
+ return noSession(target);
369
+ }
370
+ catch (e) {
371
+ process.stderr.write(`Error: ${e.message}\n`);
372
+ return 1;
373
+ }
374
+ process.stdout.write(`Deleted ${id}\n`);
375
+ return 0;
376
+ }
377
+ async function runGistList(args, localBase) {
378
+ const { flags } = parseGistArgs(args);
379
+ const target = gistTarget(flags, localBase);
380
+ const result = (await fetchJson(`${target}/api/gists`));
381
+ if (!result)
382
+ return noSession(target);
383
+ const gists = result.gists || [];
384
+ if (!gists.length) {
385
+ process.stdout.write("(no active gists)\n");
386
+ return 0;
387
+ }
388
+ for (const g of gists) {
389
+ process.stdout.write(`${g.id.padEnd(14)} ${(g.title || g.filename).padEnd(28)} ${g.url || ""}\n`);
390
+ }
391
+ return 0;
392
+ }
393
+ const parsed = parseArgs(process.argv.slice(2));
394
+ const { repo, port: portArg, host: hostArg, watch, help } = parsed;
395
+ if (help) {
396
+ printHelp();
397
+ process.exit(0);
398
+ }
399
+ // Review subcommand (pure filesystem, no daemon).
400
+ if (parsed.rest[0] === "review") {
401
+ const repoRootForReview = repo ?? process.env.REPO_ROOT ?? process.cwd();
402
+ await handleReviewCommand(parsed.rest.slice(1), repoRootForReview);
403
+ process.exit(0);
404
+ }
405
+ if (portArg != null && !Number.isFinite(portArg)) {
406
+ process.stderr.write("Invalid --port value\n");
407
+ process.exit(2);
408
+ }
409
+ const port = portArg || Number(process.env.PORT) || 7376;
410
+ const host = hostArg || process.env.HOST || "0.0.0.0";
411
+ const base = `http://${connectHost(host)}:${port}`;
412
+ // Session-management subcommands target the running daemon.
413
+ if (["ls", "rm", "stop"].includes(parsed.rest[0])) {
414
+ const code = await runSubcommand(parsed.rest[0], parsed, base, port, host);
415
+ process.exit(code);
416
+ }
417
+ // Publish an ephemeral gist to the session daemon.
418
+ if (parsed.rest[0] === "gist") {
419
+ const code = await runGist(parsed.rest.slice(1), base);
420
+ process.exit(code);
421
+ }
422
+ const repoRoot = repo ?? process.env.REPO_ROOT ?? process.cwd();
423
+ const repoRootAbs = path.resolve(repoRoot);
424
+ async function joinExisting() {
425
+ const info = await probeSession(base);
426
+ if (!info)
427
+ return false;
428
+ if (info.app !== "repoview") {
429
+ process.stderr.write(`Port ${port} is in use by something that isn't repoview. Use --port to pick another.\n`);
430
+ process.exit(1);
431
+ }
432
+ const registered = await registerRepo(base, repoRootAbs, watch);
433
+ process.stdout.write(`Joined repoview session on port ${port}\n` +
434
+ `${registered.name} → http://${connectHost(host)}:${port}${registered.url}\n`);
435
+ return true;
436
+ }
437
+ // Try to join an existing session first; otherwise become the daemon.
438
+ if (await joinExisting()) {
439
+ process.exit(0);
440
+ }
441
+ try {
442
+ await startServer({ repoRoot: repoRootAbs, port, host, watch });
443
+ }
444
+ catch (e) {
445
+ if (e.code === "EADDRINUSE") {
446
+ // Lost a startup race — another daemon just bound the port. Join it.
447
+ if (await joinExisting())
448
+ process.exit(0);
449
+ process.stderr.write(`Port ${port} is already in use.\n`);
450
+ process.exit(1);
451
+ }
452
+ throw e;
453
+ }
454
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/csv.js ADDED
@@ -0,0 +1,64 @@
1
+ export function parseCsv(text, delimiter = ",") {
2
+ const rows = [];
3
+ let current = [];
4
+ let cell = "";
5
+ let inQuotes = false;
6
+ for (let i = 0; i < text.length; i++) {
7
+ const ch = text[i];
8
+ if (inQuotes) {
9
+ if (ch === '"' && text[i + 1] === '"') {
10
+ cell += '"';
11
+ i++;
12
+ }
13
+ else if (ch === '"') {
14
+ inQuotes = false;
15
+ }
16
+ else {
17
+ cell += ch;
18
+ }
19
+ }
20
+ else {
21
+ if (ch === '"') {
22
+ inQuotes = true;
23
+ }
24
+ else if (ch === delimiter) {
25
+ current.push(cell);
26
+ cell = "";
27
+ }
28
+ else if (ch === "\n" || (ch === "\r" && text[i + 1] === "\n")) {
29
+ if (ch === "\r")
30
+ i++;
31
+ current.push(cell);
32
+ rows.push(current);
33
+ current = [];
34
+ cell = "";
35
+ }
36
+ else if (ch === "\r") {
37
+ current.push(cell);
38
+ rows.push(current);
39
+ current = [];
40
+ cell = "";
41
+ }
42
+ else {
43
+ cell += ch;
44
+ }
45
+ }
46
+ }
47
+ if (cell || current.length) {
48
+ current.push(cell);
49
+ rows.push(current);
50
+ }
51
+ return rows;
52
+ }
53
+ export function renderCsvTable(rows, escFn) {
54
+ if (!rows.length)
55
+ return "<p>Empty file</p>";
56
+ const header = rows[0];
57
+ const body = rows.slice(1);
58
+ const ths = header.map((h) => `<th>${escFn(h)}</th>`).join("");
59
+ const trs = body
60
+ .map((row) => `<tr>${row.map((c) => `<td>${escFn(c)}</td>`).join("")}</tr>`)
61
+ .join("\n");
62
+ return `<div class="csv-table-wrap"><table class="csv-table"><thead><tr>${ths}</tr></thead><tbody>${trs}</tbody></table></div>`;
63
+ }
64
+ //# sourceMappingURL=csv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv.js","sourceRoot":"","sources":["../src/csv.ts"],"names":[],"mappings":"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"}
package/dist/format.js ADDED
@@ -0,0 +1,25 @@
1
+ export function formatBytes(bytes) {
2
+ if (!Number.isFinite(bytes))
3
+ return "";
4
+ if (bytes < 1024)
5
+ return `${bytes} B`;
6
+ const units = ["KB", "MB", "GB", "TB"];
7
+ let value = bytes / 1024;
8
+ let unit = 0;
9
+ while (value >= 1024 && unit < units.length - 1) {
10
+ value /= 1024;
11
+ unit++;
12
+ }
13
+ return `${value.toFixed(value < 10 ? 1 : 0)} ${units[unit]}`;
14
+ }
15
+ export function formatDate(ms) {
16
+ const d = new Date(ms);
17
+ return d.toLocaleString(undefined, {
18
+ year: "numeric",
19
+ month: "short",
20
+ day: "2-digit",
21
+ hour: "2-digit",
22
+ minute: "2-digit",
23
+ });
24
+ }
25
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAC;IACtC,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;IACzB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,KAAK,IAAI,IAAI,CAAC;QACd,IAAI,EAAE,CAAC;IACT,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE;QACjC,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC;AACL,CAAC"}