saturndocs 0.1.0

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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/dist/auth-FRCFGNYT.js +14 -0
  3. package/dist/brokenLinks-TTOBP4P7.js +48 -0
  4. package/dist/build-F5PWGP57.js +39 -0
  5. package/dist/chunk-3P2OFTXR.js +71 -0
  6. package/dist/chunk-3V753MRI.js +100 -0
  7. package/dist/chunk-5KX4ZK5E.js +104 -0
  8. package/dist/chunk-CMNX5DLQ.js +119 -0
  9. package/dist/chunk-GYRVGWDM.js +3499 -0
  10. package/dist/chunk-I6U4V7B4.js +1552 -0
  11. package/dist/chunk-J6P3VGGE.js +21 -0
  12. package/dist/chunk-KGJESHJC.js +37 -0
  13. package/dist/chunk-M2BZEDAS.js +57 -0
  14. package/dist/chunk-N7QPZMLP.js +82 -0
  15. package/dist/chunk-OEAEX5YW.js +51 -0
  16. package/dist/chunk-OZWTXMO3.js +584 -0
  17. package/dist/chunk-QLFODLVN.js +46 -0
  18. package/dist/chunk-R3X2DPFF.js +568 -0
  19. package/dist/chunk-S45UWCML.js +588 -0
  20. package/dist/chunk-SABK3R2P.js +2452 -0
  21. package/dist/chunk-STCCGFKC.js +246 -0
  22. package/dist/chunk-TKISMN3P.js +39 -0
  23. package/dist/chunk-U7PKMSB3.js +465 -0
  24. package/dist/chunk-VNYDYHXM.js +22 -0
  25. package/dist/chunk-VXEUNRVA.js +26 -0
  26. package/dist/chunk-XO4CUC7V.js +99 -0
  27. package/dist/cli.d.ts +1 -0
  28. package/dist/cli.js +95 -0
  29. package/dist/deploy-QU7DCKWU.js +11 -0
  30. package/dist/dev-VDSDCBO2.js +43 -0
  31. package/dist/index.d.ts +382 -0
  32. package/dist/index.js +191 -0
  33. package/dist/init-7T5TEPBH.js +14 -0
  34. package/dist/manage-MKH27U3B.js +12 -0
  35. package/dist/openapiCheck-KGBQJTIQ.js +66 -0
  36. package/dist/pages-HIPXRLSY.js +15 -0
  37. package/dist/read-DMSJUEDA.js +160 -0
  38. package/dist/read-ZEVUZNNB.js +146 -0
  39. package/dist/requests-H5MIGBIS.js +13 -0
  40. package/dist/schema-XJUEZSIW.js +13 -0
  41. package/dist/sites-I4WI2MPG.js +14 -0
  42. package/dist/status-7R3NOI5H.js +14 -0
  43. package/dist/suggestions-4WFQ3APX.js +739 -0
  44. package/dist/validate-VXL4PL42.js +30 -0
  45. package/package.json +68 -0
@@ -0,0 +1,21 @@
1
+ // src/lib/table.ts
2
+ function renderTable(headers, rows) {
3
+ const columnCount = headers.length;
4
+ const widths = headers.map((header, columnIndex) => {
5
+ let width = header.length;
6
+ for (const row of rows) {
7
+ const cell = row[columnIndex] ?? "";
8
+ if (cell.length > width) width = cell.length;
9
+ }
10
+ return width;
11
+ });
12
+ const padRow = (cells) => cells.map(
13
+ (cell, columnIndex) => columnIndex === columnCount - 1 ? cell : cell.padEnd(widths[columnIndex] ?? 0)
14
+ ).join(" ").trimEnd();
15
+ const divider = widths.map((width) => "-".repeat(width)).join(" ");
16
+ return [padRow(headers), divider, ...rows.map(padRow)].join("\n");
17
+ }
18
+
19
+ export {
20
+ renderTable
21
+ };
@@ -0,0 +1,37 @@
1
+ import {
2
+ EXIT,
3
+ failureResult,
4
+ interrupted
5
+ } from "./chunk-GYRVGWDM.js";
6
+
7
+ // src/adapter/signals.ts
8
+ var active = null;
9
+ function interruptSignal() {
10
+ return active;
11
+ }
12
+ function installInterrupt(options) {
13
+ const source = options.source ?? process;
14
+ const exit = options.exit ?? ((code) => process.exit(code));
15
+ const controller = new AbortController();
16
+ const handler = () => {
17
+ controller.abort(interrupted());
18
+ const context = options.context();
19
+ options.writer.write(failureResult(interrupted(), context));
20
+ source.off("SIGINT", handler);
21
+ exit(EXIT.interrupted);
22
+ };
23
+ source.on("SIGINT", handler);
24
+ active = controller.signal;
25
+ return {
26
+ signal: controller.signal,
27
+ dispose() {
28
+ if (active === controller.signal) active = null;
29
+ source.off("SIGINT", handler);
30
+ }
31
+ };
32
+ }
33
+
34
+ export {
35
+ interruptSignal,
36
+ installInterrupt
37
+ };
@@ -0,0 +1,57 @@
1
+ // src/adapter/help.ts
2
+ var GLOBAL_LONGS = /* @__PURE__ */ new Set(["--json", "--site", "--api", "--input", "--no-input", "--timeout"]);
3
+ function syntaxOf(flag) {
4
+ if (flag.value === "boolean") return flag.name;
5
+ const placeholder = flag.value === "integer" ? "n" : flag.name.replace(/^--/u, "");
6
+ return `${flag.name} <${placeholder}>`;
7
+ }
8
+ function textLine(metadata) {
9
+ const { requirement, limit, sources } = metadata.text;
10
+ if (requirement === "none") return null;
11
+ const cap = limit === null ? "" : `, at most ${limit} characters`;
12
+ return `Text (${requirement}): ${sources.join(", ")}${cap}.`;
13
+ }
14
+ function permissionLine(metadata) {
15
+ const server = metadata.permissions.server ?? "none";
16
+ const preflight = metadata.permissions.preflight;
17
+ return preflight === null ? `Permission: ${server}.` : `Permission: ${server}, after a ${preflight} check that the credential names --site.`;
18
+ }
19
+ function targetLine(metadata) {
20
+ if (metadata.target.site === "required") return "Target: --site is required and must match the credential's site.";
21
+ if (metadata.target.site === "inferred") return "Target: --site is optional; the credential's own site is used.";
22
+ return "Target: no site. Nothing leaves this process.";
23
+ }
24
+ function helpBody(metadata) {
25
+ const lines = [
26
+ "",
27
+ metadata.description,
28
+ "",
29
+ targetLine(metadata),
30
+ permissionLine(metadata),
31
+ textLine(metadata),
32
+ `Side effects: ${metadata.side_effects.effect}`,
33
+ `Exit codes: ${metadata.exits.join(", ")}.`,
34
+ "",
35
+ "Examples:",
36
+ ...metadata.examples.map((example) => ` ${example.command}
37
+ ${example.description}`),
38
+ ""
39
+ ];
40
+ return lines.filter((line) => line !== null).join("\n");
41
+ }
42
+ function applyCommandHelp(command, metadata) {
43
+ command.description(metadata.summary);
44
+ const declared = new Set(command.options.map((option) => option.long));
45
+ for (const flag of metadata.flags) {
46
+ if (GLOBAL_LONGS.has(flag.name) || declared.has(flag.name)) continue;
47
+ if (flag.required) command.requiredOption(syntaxOf(flag), flag.description);
48
+ else command.option(syntaxOf(flag), flag.description);
49
+ }
50
+ command.addHelpText("after", helpBody(metadata));
51
+ return command;
52
+ }
53
+
54
+ export {
55
+ helpBody,
56
+ applyCommandHelp
57
+ };
@@ -0,0 +1,82 @@
1
+ import {
2
+ invalidInput
3
+ } from "./chunk-GYRVGWDM.js";
4
+
5
+ // src/adapter/input.ts
6
+ import { readFile } from "fs/promises";
7
+ var STDIN_BYTE_CEILING = 1048576;
8
+ function countCodePoints(text) {
9
+ return Array.from(text).length;
10
+ }
11
+ async function readStdin(source, byteCeiling, command) {
12
+ if (source.isTTY === true) {
13
+ throw invalidInput(`${command} was told to read the text from stdin, but stdin is a terminal. Pipe the text in, or use --text or --file <path>.`);
14
+ }
15
+ const decoder = new TextDecoder();
16
+ let text = "";
17
+ let bytes = 0;
18
+ for await (const chunk of source) {
19
+ const buffer = typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk;
20
+ bytes += buffer.byteLength;
21
+ if (bytes > byteCeiling) {
22
+ throw invalidInput(`${command} read more than ${byteCeiling} bytes from stdin. Nothing was sent.`);
23
+ }
24
+ text += decoder.decode(buffer, { stream: true });
25
+ }
26
+ return text + decoder.decode();
27
+ }
28
+ async function readTextInput(flags, options) {
29
+ const { command, requirement, limit } = options;
30
+ const given = [flags.text === void 0 ? null : "--text", flags.file === void 0 ? null : "--file"].filter(
31
+ (name) => name !== null
32
+ );
33
+ if (requirement === "none" && given.length > 0) {
34
+ throw invalidInput(`${command} takes no text, and ${given.join(" and ")} was given.`);
35
+ }
36
+ if (given.length > 1) {
37
+ throw invalidInput(`${command} takes exactly one of --text or --file. Both were given.`);
38
+ }
39
+ if (given.length === 0) {
40
+ if (requirement === "required") {
41
+ throw invalidInput(`${command} needs text. Pass --text <text>, --file <path>, or --file - to read stdin.`);
42
+ }
43
+ return null;
44
+ }
45
+ const byteCeiling = limit === null ? STDIN_BYTE_CEILING : Math.min(STDIN_BYTE_CEILING, limit * 4 + 1);
46
+ let text;
47
+ if (flags.text !== void 0) {
48
+ text = flags.text;
49
+ } else if (flags.file === "-") {
50
+ const stdin = options.stdin ?? process.stdin;
51
+ if (options.interactive === false && stdin.isTTY === true) {
52
+ throw invalidInput(`${command} cannot read stdin under --no-input from a terminal.`);
53
+ }
54
+ text = await readStdin(stdin, byteCeiling, command);
55
+ } else {
56
+ const path = flags.file;
57
+ const read = options.readFileImpl ?? ((target) => readFile(target, "utf8"));
58
+ try {
59
+ text = await read(path);
60
+ } catch (error) {
61
+ throw invalidInput(`${command} could not read ${path}: ${error instanceof Error ? error.message : String(error)}`, {
62
+ cause: error
63
+ });
64
+ }
65
+ }
66
+ if (text.trim() === "") {
67
+ if (requirement === "required") throw invalidInput(`${command} was given empty text.`);
68
+ return null;
69
+ }
70
+ if (limit !== null) {
71
+ const size = countCodePoints(text);
72
+ if (size > limit) {
73
+ throw invalidInput(`${command} accepts at most ${limit} characters and was given ${size}. Nothing was sent.`);
74
+ }
75
+ }
76
+ return text;
77
+ }
78
+
79
+ export {
80
+ STDIN_BYTE_CEILING,
81
+ readTextInput
82
+ };
@@ -0,0 +1,51 @@
1
+ // src/lib/links.ts
2
+ import { existsSync } from "fs";
3
+ import { readFile } from "fs/promises";
4
+ import { dirname, extname, join, relative } from "path";
5
+ import fg from "fast-glob";
6
+ function isInternalLink(href) {
7
+ if (href === "") return false;
8
+ if (href.startsWith("#")) return false;
9
+ if (href.startsWith("//")) return false;
10
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(href)) return false;
11
+ return true;
12
+ }
13
+ function candidatePaths(distDir, htmlFile, href) {
14
+ const path = href.split("#")[0].split("?")[0];
15
+ if (path === "") return [];
16
+ const base = path.startsWith("/") ? join(distDir, path) : join(dirname(htmlFile), path);
17
+ if (path.endsWith("/")) {
18
+ return [join(base, "index.html")];
19
+ }
20
+ if (extname(base) !== "") {
21
+ return [base];
22
+ }
23
+ return [base, `${base}.html`, join(base, "index.html")];
24
+ }
25
+ async function scanBrokenLinks(distDir) {
26
+ const htmlFiles = await fg("**/*.html", { cwd: distDir, absolute: true });
27
+ const attrRe = /(?:href|src)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi;
28
+ const seen = /* @__PURE__ */ new Set();
29
+ const misses = [];
30
+ for (const htmlFile of htmlFiles) {
31
+ const html = await readFile(htmlFile, "utf8");
32
+ const source = relative(distDir, htmlFile);
33
+ let match;
34
+ while ((match = attrRe.exec(html)) !== null) {
35
+ const href = (match[1] ?? match[2] ?? "").trim();
36
+ if (!isInternalLink(href)) continue;
37
+ const candidates = candidatePaths(distDir, htmlFile, href);
38
+ if (candidates.length === 0) continue;
39
+ if (candidates.some((candidate) => existsSync(candidate))) continue;
40
+ const key = `${source}\0${href}`;
41
+ if (seen.has(key)) continue;
42
+ seen.add(key);
43
+ misses.push({ source, href });
44
+ }
45
+ }
46
+ return misses;
47
+ }
48
+
49
+ export {
50
+ scanBrokenLinks
51
+ };