@hawkeyexl/manni 4.8.1 → 4.10.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 (173) hide show
  1. package/README.md +1 -1
  2. package/dist/{batch-QMHYWGUA.js → batch-6NICDKRE.js} +12 -12
  3. package/dist/{build-ZGA3O3P4.js → build-3KP2K3XN.js} +11 -11
  4. package/dist/{calibrate-KBMFGKP3.js → calibrate-LUA3DWKD.js} +13 -13
  5. package/dist/{capture-C46UXFRK.js → capture-NETOHCB4.js} +12 -12
  6. package/dist/{check-UMI5ACCE.js → check-7B77ZD2N.js} +11 -11
  7. package/dist/{check-OAJWC3WD.js → check-E4QCB7LS.js} +5 -5
  8. package/dist/{check-CORYIW76.js → check-NLL4NRYA.js} +13 -13
  9. package/dist/{check-LLQ6PJV3.js → check-PTECPIIB.js} +10 -10
  10. package/dist/{chunk-N7J5C35C.js → chunk-2BV4FBC7.js} +2 -2
  11. package/dist/chunk-2BV4FBC7.js.map +1 -0
  12. package/dist/{chunk-PO5W6JAP.js → chunk-2JV7C4YV.js} +7 -7
  13. package/dist/{chunk-Z27GYQOY.js → chunk-2UCC26MO.js} +8 -8
  14. package/dist/{chunk-WBETAXO2.js → chunk-2W34HX2U.js} +5 -5
  15. package/dist/{chunk-ZIGIJBXG.js → chunk-2YJ5H5E6.js} +9 -9
  16. package/dist/{chunk-HWNSIEZK.js → chunk-3E2X2RBU.js} +6 -6
  17. package/dist/{chunk-Q3GFZJTY.js → chunk-4DLF5SA4.js} +35 -17
  18. package/dist/chunk-4DLF5SA4.js.map +1 -0
  19. package/dist/{chunk-BYVH727K.js → chunk-55GMOVKW.js} +2 -2
  20. package/dist/{chunk-C2JPBQCJ.js → chunk-5REEVKGH.js} +2 -2
  21. package/dist/{chunk-XXDXIIQ4.js → chunk-6AGESHHM.js} +2 -2
  22. package/dist/{chunk-GQBVZS5G.js → chunk-6LR73NMO.js} +6 -6
  23. package/dist/{chunk-XKBEHKWO.js → chunk-6M5VJOC2.js} +2 -1
  24. package/dist/{chunk-F734HIHT.js → chunk-7Y3N4Y72.js} +3 -3
  25. package/dist/{chunk-WUFP4V7B.js → chunk-ABHG6I3G.js} +1292 -126
  26. package/dist/chunk-ABHG6I3G.js.map +1 -0
  27. package/dist/{chunk-FEALEYSE.js → chunk-AO5TSDKT.js} +4 -4
  28. package/dist/{chunk-LF6FOF6U.js → chunk-BD7IXBWE.js} +15 -26
  29. package/dist/{chunk-LF6FOF6U.js.map → chunk-BD7IXBWE.js.map} +1 -1
  30. package/dist/{chunk-NB4ILZMQ.js → chunk-CCWMACJL.js} +8 -8
  31. package/dist/{chunk-K43X5VDR.js → chunk-D2UW3ZCK.js} +6 -6
  32. package/dist/{chunk-SV6UEQCU.js → chunk-DFCQ6BMI.js} +4 -4
  33. package/dist/{chunk-ECVQNGTH.js → chunk-DNZUBCGZ.js} +3 -3
  34. package/dist/{chunk-POGYWOJ2.js → chunk-EAUIQADY.js} +3 -3
  35. package/dist/{chunk-XDS3KQCK.js → chunk-G6FNWRAI.js} +4 -4
  36. package/dist/{chunk-6HMLYFEU.js → chunk-G7XD4QH5.js} +810 -5
  37. package/dist/chunk-G7XD4QH5.js.map +1 -0
  38. package/dist/{chunk-WUXD6VBD.js → chunk-GB2XPITA.js} +2 -2
  39. package/dist/{chunk-KPXOJMQ6.js → chunk-GCKHSBEN.js} +2 -2
  40. package/dist/{chunk-6QBJHRFC.js → chunk-GDLHTI5R.js} +129 -26
  41. package/dist/chunk-GDLHTI5R.js.map +1 -0
  42. package/dist/{chunk-NNFSIRVE.js → chunk-GXN7RRHR.js} +3 -3
  43. package/dist/{chunk-RCS5YFY2.js → chunk-H26VDFDS.js} +2 -2
  44. package/dist/{chunk-4VQBHTGA.js → chunk-IJ62BB2T.js} +5 -5
  45. package/dist/{chunk-WT6HMEEF.js → chunk-KBG463UK.js} +35 -8
  46. package/dist/{chunk-WT6HMEEF.js.map → chunk-KBG463UK.js.map} +1 -1
  47. package/dist/{chunk-UWY4B2PM.js → chunk-LQZQ5KGG.js} +4 -4
  48. package/dist/{chunk-VSOYZ7QH.js → chunk-PK7EKJ5T.js} +4 -4
  49. package/dist/{chunk-YVVMC4SZ.js → chunk-QBVP3SQP.js} +4 -4
  50. package/dist/{chunk-6MNOMHFI.js → chunk-QJRQ4BRC.js} +11 -11
  51. package/dist/{chunk-7LC4YJJ3.js → chunk-RODZ7MB7.js} +3 -3
  52. package/dist/{chunk-SXODK43S.js → chunk-RZVCWX5R.js} +4 -4
  53. package/dist/{chunk-5LAKRYXU.js → chunk-SUTMSDQ2.js} +3 -3
  54. package/dist/{chunk-6KKZXB2O.js → chunk-VVVKBUBO.js} +2 -2
  55. package/dist/{chunk-6ZR24A4S.js → chunk-VZVEP2OZ.js} +2 -2
  56. package/dist/{chunk-3FG2UU3H.js → chunk-WN47MNSK.js} +4 -4
  57. package/dist/{chunk-LAU6SVTJ.js → chunk-XU73V5XT.js} +7 -7
  58. package/dist/{chunk-77L5GNVO.js → chunk-Z5YHMRLF.js} +2 -2
  59. package/dist/{chunk-AO66Q66S.js → chunk-ZHRPH52H.js} +2 -2
  60. package/dist/chunk-ZMECS2IJ.js +27 -0
  61. package/dist/chunk-ZMECS2IJ.js.map +1 -0
  62. package/dist/{chunk-VD3EQSBI.js → chunk-ZXXFP2LA.js} +2 -2
  63. package/dist/{cli-SBJY2NQH.js → cli-4YYC6LCY.js} +15 -15
  64. package/dist/{cli-4B5RWL7P.js → cli-BIIUKPTE.js} +13 -12
  65. package/dist/{cli-4B5RWL7P.js.map → cli-BIIUKPTE.js.map} +1 -1
  66. package/dist/{cli-XIQKPNA7.js → cli-EH3I4IUX.js} +32 -32
  67. package/dist/cli-EH3I4IUX.js.map +1 -0
  68. package/dist/{cli-MNNOXWYU.js → cli-HO62TOM2.js} +8 -8
  69. package/dist/cli-LWST5FQH.js +839 -0
  70. package/dist/cli-LWST5FQH.js.map +1 -0
  71. package/dist/{cli-UB5W75GJ.js → cli-P2X7PNY6.js} +12 -12
  72. package/dist/{cli-QR3ZQZA4.js → cli-SGVFZOAW.js} +19 -19
  73. package/dist/{cli-5AML7QR2.js → cli-TELPAMJO.js} +14 -14
  74. package/dist/{cli-I4GBPLRM.js → cli-UETKXHJN.js} +3 -3
  75. package/dist/{cli-WWDARAWS.js → cli-V2DI3K2R.js} +14 -14
  76. package/dist/cli.js +18 -11
  77. package/dist/cli.js.map +1 -1
  78. package/dist/{config-YWSNBFEE.js → config-TYXYQK3I.js} +3 -3
  79. package/dist/docmeta.js +7 -7
  80. package/dist/{github-TIZ3ZR3D.js → github-ESK45CEZ.js} +10 -10
  81. package/dist/{github-WKOJRW7P.js → github-WER7JUTN.js} +12 -12
  82. package/dist/index.js +35 -34
  83. package/dist/index.js.map +1 -1
  84. package/dist/{json-4FUOZ3XX.js → json-QR4G35KA.js} +10 -10
  85. package/dist/{lint-7VQFESHK.js → lint-QTI7XK2A.js} +11 -10
  86. package/dist/{list-7U2MBDIM.js → list-JO4G3TS3.js} +10 -10
  87. package/dist/{list-W6EUAOBV.js → list-O2MJUP5V.js} +10 -10
  88. package/dist/{page-WZLBKSCD.js → page-FSXDXCDD.js} +9 -9
  89. package/dist/{prepare-FPEWAHJH.js → prepare-UPIBTFNS.js} +11 -11
  90. package/dist/{pretty-7M4X4TCY.js → pretty-4IONWSEP.js} +10 -10
  91. package/dist/{pretty-CUCMQU5R.js → pretty-R4BQD2VH.js} +11 -11
  92. package/dist/{reporters-DQVSDXV6.js → reporters-DHO2BXAD.js} +5 -5
  93. package/dist/{reporters-KYJE54JS.js → reporters-FPP6JNDP.js} +9 -9
  94. package/dist/{run-ABGXGOGQ.js → run-YH5Z7RJ7.js} +10 -10
  95. package/dist/{term-HTIG3YDC.js → term-ASM4LVYC.js} +279 -150
  96. package/dist/term-ASM4LVYC.js.map +1 -0
  97. package/dist/{validate-HWNU3MDY.js → validate-7JI3H57P.js} +5 -5
  98. package/package.json +1 -1
  99. package/plugin/manni/.claude-plugin/plugin.json +1 -1
  100. package/dist/chunk-6HMLYFEU.js.map +0 -1
  101. package/dist/chunk-6QBJHRFC.js.map +0 -1
  102. package/dist/chunk-N7J5C35C.js.map +0 -1
  103. package/dist/chunk-Q3GFZJTY.js.map +0 -1
  104. package/dist/chunk-WUFP4V7B.js.map +0 -1
  105. package/dist/cli-XIQKPNA7.js.map +0 -1
  106. package/dist/term-HTIG3YDC.js.map +0 -1
  107. /package/dist/{batch-QMHYWGUA.js.map → batch-6NICDKRE.js.map} +0 -0
  108. /package/dist/{build-ZGA3O3P4.js.map → build-3KP2K3XN.js.map} +0 -0
  109. /package/dist/{calibrate-KBMFGKP3.js.map → calibrate-LUA3DWKD.js.map} +0 -0
  110. /package/dist/{capture-C46UXFRK.js.map → capture-NETOHCB4.js.map} +0 -0
  111. /package/dist/{check-LLQ6PJV3.js.map → check-7B77ZD2N.js.map} +0 -0
  112. /package/dist/{check-OAJWC3WD.js.map → check-E4QCB7LS.js.map} +0 -0
  113. /package/dist/{check-CORYIW76.js.map → check-NLL4NRYA.js.map} +0 -0
  114. /package/dist/{check-UMI5ACCE.js.map → check-PTECPIIB.js.map} +0 -0
  115. /package/dist/{chunk-PO5W6JAP.js.map → chunk-2JV7C4YV.js.map} +0 -0
  116. /package/dist/{chunk-Z27GYQOY.js.map → chunk-2UCC26MO.js.map} +0 -0
  117. /package/dist/{chunk-WBETAXO2.js.map → chunk-2W34HX2U.js.map} +0 -0
  118. /package/dist/{chunk-ZIGIJBXG.js.map → chunk-2YJ5H5E6.js.map} +0 -0
  119. /package/dist/{chunk-HWNSIEZK.js.map → chunk-3E2X2RBU.js.map} +0 -0
  120. /package/dist/{chunk-BYVH727K.js.map → chunk-55GMOVKW.js.map} +0 -0
  121. /package/dist/{chunk-C2JPBQCJ.js.map → chunk-5REEVKGH.js.map} +0 -0
  122. /package/dist/{chunk-XXDXIIQ4.js.map → chunk-6AGESHHM.js.map} +0 -0
  123. /package/dist/{chunk-GQBVZS5G.js.map → chunk-6LR73NMO.js.map} +0 -0
  124. /package/dist/{chunk-XKBEHKWO.js.map → chunk-6M5VJOC2.js.map} +0 -0
  125. /package/dist/{chunk-F734HIHT.js.map → chunk-7Y3N4Y72.js.map} +0 -0
  126. /package/dist/{chunk-FEALEYSE.js.map → chunk-AO5TSDKT.js.map} +0 -0
  127. /package/dist/{chunk-NB4ILZMQ.js.map → chunk-CCWMACJL.js.map} +0 -0
  128. /package/dist/{chunk-K43X5VDR.js.map → chunk-D2UW3ZCK.js.map} +0 -0
  129. /package/dist/{chunk-SV6UEQCU.js.map → chunk-DFCQ6BMI.js.map} +0 -0
  130. /package/dist/{chunk-ECVQNGTH.js.map → chunk-DNZUBCGZ.js.map} +0 -0
  131. /package/dist/{chunk-POGYWOJ2.js.map → chunk-EAUIQADY.js.map} +0 -0
  132. /package/dist/{chunk-XDS3KQCK.js.map → chunk-G6FNWRAI.js.map} +0 -0
  133. /package/dist/{chunk-WUXD6VBD.js.map → chunk-GB2XPITA.js.map} +0 -0
  134. /package/dist/{chunk-KPXOJMQ6.js.map → chunk-GCKHSBEN.js.map} +0 -0
  135. /package/dist/{chunk-NNFSIRVE.js.map → chunk-GXN7RRHR.js.map} +0 -0
  136. /package/dist/{chunk-RCS5YFY2.js.map → chunk-H26VDFDS.js.map} +0 -0
  137. /package/dist/{chunk-4VQBHTGA.js.map → chunk-IJ62BB2T.js.map} +0 -0
  138. /package/dist/{chunk-UWY4B2PM.js.map → chunk-LQZQ5KGG.js.map} +0 -0
  139. /package/dist/{chunk-VSOYZ7QH.js.map → chunk-PK7EKJ5T.js.map} +0 -0
  140. /package/dist/{chunk-YVVMC4SZ.js.map → chunk-QBVP3SQP.js.map} +0 -0
  141. /package/dist/{chunk-6MNOMHFI.js.map → chunk-QJRQ4BRC.js.map} +0 -0
  142. /package/dist/{chunk-7LC4YJJ3.js.map → chunk-RODZ7MB7.js.map} +0 -0
  143. /package/dist/{chunk-SXODK43S.js.map → chunk-RZVCWX5R.js.map} +0 -0
  144. /package/dist/{chunk-5LAKRYXU.js.map → chunk-SUTMSDQ2.js.map} +0 -0
  145. /package/dist/{chunk-6KKZXB2O.js.map → chunk-VVVKBUBO.js.map} +0 -0
  146. /package/dist/{chunk-6ZR24A4S.js.map → chunk-VZVEP2OZ.js.map} +0 -0
  147. /package/dist/{chunk-3FG2UU3H.js.map → chunk-WN47MNSK.js.map} +0 -0
  148. /package/dist/{chunk-LAU6SVTJ.js.map → chunk-XU73V5XT.js.map} +0 -0
  149. /package/dist/{chunk-77L5GNVO.js.map → chunk-Z5YHMRLF.js.map} +0 -0
  150. /package/dist/{chunk-AO66Q66S.js.map → chunk-ZHRPH52H.js.map} +0 -0
  151. /package/dist/{chunk-VD3EQSBI.js.map → chunk-ZXXFP2LA.js.map} +0 -0
  152. /package/dist/{cli-SBJY2NQH.js.map → cli-4YYC6LCY.js.map} +0 -0
  153. /package/dist/{cli-MNNOXWYU.js.map → cli-HO62TOM2.js.map} +0 -0
  154. /package/dist/{cli-UB5W75GJ.js.map → cli-P2X7PNY6.js.map} +0 -0
  155. /package/dist/{cli-QR3ZQZA4.js.map → cli-SGVFZOAW.js.map} +0 -0
  156. /package/dist/{cli-5AML7QR2.js.map → cli-TELPAMJO.js.map} +0 -0
  157. /package/dist/{cli-I4GBPLRM.js.map → cli-UETKXHJN.js.map} +0 -0
  158. /package/dist/{cli-WWDARAWS.js.map → cli-V2DI3K2R.js.map} +0 -0
  159. /package/dist/{config-YWSNBFEE.js.map → config-TYXYQK3I.js.map} +0 -0
  160. /package/dist/{github-TIZ3ZR3D.js.map → github-ESK45CEZ.js.map} +0 -0
  161. /package/dist/{github-WKOJRW7P.js.map → github-WER7JUTN.js.map} +0 -0
  162. /package/dist/{json-4FUOZ3XX.js.map → json-QR4G35KA.js.map} +0 -0
  163. /package/dist/{lint-7VQFESHK.js.map → lint-QTI7XK2A.js.map} +0 -0
  164. /package/dist/{list-7U2MBDIM.js.map → list-JO4G3TS3.js.map} +0 -0
  165. /package/dist/{list-W6EUAOBV.js.map → list-O2MJUP5V.js.map} +0 -0
  166. /package/dist/{page-WZLBKSCD.js.map → page-FSXDXCDD.js.map} +0 -0
  167. /package/dist/{prepare-FPEWAHJH.js.map → prepare-UPIBTFNS.js.map} +0 -0
  168. /package/dist/{pretty-7M4X4TCY.js.map → pretty-4IONWSEP.js.map} +0 -0
  169. /package/dist/{pretty-CUCMQU5R.js.map → pretty-R4BQD2VH.js.map} +0 -0
  170. /package/dist/{reporters-DQVSDXV6.js.map → reporters-DHO2BXAD.js.map} +0 -0
  171. /package/dist/{reporters-KYJE54JS.js.map → reporters-FPP6JNDP.js.map} +0 -0
  172. /package/dist/{run-ABGXGOGQ.js.map → run-YH5Z7RJ7.js.map} +0 -0
  173. /package/dist/{validate-HWNU3MDY.js.map → validate-7JI3H57P.js.map} +0 -0
@@ -0,0 +1,839 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ launcherCommandLine
4
+ } from "./chunk-ZMECS2IJ.js";
5
+ import {
6
+ fail
7
+ } from "./chunk-YEUYKR62.js";
8
+ import {
9
+ FAMILY_CONFIG_NAMES,
10
+ findConfigFileSync,
11
+ readConfigFileSync,
12
+ searchPath
13
+ } from "./chunk-6M5VJOC2.js";
14
+ import {
15
+ notice,
16
+ warn
17
+ } from "./chunk-HX44GB4Z.js";
18
+ import "./chunk-QCHVR4ZM.js";
19
+ import {
20
+ package_default
21
+ } from "./chunk-2BV4FBC7.js";
22
+ import "./chunk-OWBRDNRZ.js";
23
+ import {
24
+ ToolError,
25
+ errorMessage
26
+ } from "./chunk-G3T47CFV.js";
27
+ import "./chunk-2H7UOFLK.js";
28
+
29
+ // src/site/cli.ts
30
+ import { Command } from "commander";
31
+
32
+ // src/site/core/detect.ts
33
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
34
+ import { dirname, join, posix, relative, resolve as resolve2 } from "node:path";
35
+
36
+ // src/site/errors.ts
37
+ var SiteError = class extends ToolError {
38
+ constructor(message) {
39
+ super(message);
40
+ this.name = "SiteError";
41
+ }
42
+ };
43
+
44
+ // src/site/core/config.ts
45
+ import { resolve } from "node:path";
46
+ var SECTION = "site";
47
+ var CONFIG_KEYS = ["dir", "commands"];
48
+ var COMMAND_KEYS = ["start", "build", "preview"];
49
+ var CONFIG_FILE = {
50
+ section: SECTION,
51
+ legacyNames: [],
52
+ toError: (message) => new SiteError(message)
53
+ };
54
+ function loadSiteConfig(cwd, configPath) {
55
+ const file = configPath === void 0 ? findConfigFileSync(cwd, CONFIG_FILE) : readConfigFileSync(configPath, cwd, CONFIG_FILE);
56
+ if (file === null) return { commands: {}, collections: [], configDir: null };
57
+ return {
58
+ ...parseSiteConfig(file.value, file.source, file.dir),
59
+ collections: file.collections,
60
+ configDir: file.dir
61
+ };
62
+ }
63
+ function parseSiteConfig(value, source, configDir) {
64
+ const obj = asMapping(value, SECTION, CONFIG_KEYS, source);
65
+ const config = { commands: {} };
66
+ if (obj.dir !== void 0) {
67
+ config.dir = resolve(configDir, asString(obj.dir, "dir", source));
68
+ }
69
+ const commands = asMapping(obj.commands, `${SECTION}.commands`, COMMAND_KEYS, source);
70
+ for (const verb of COMMAND_KEYS) {
71
+ const command = commands[verb];
72
+ if (command !== void 0) {
73
+ const line = asString(command, `commands.${verb}`, source);
74
+ if (line.trim() === "") {
75
+ throw new SiteError(`${source}: ${SECTION}.commands.${verb} must not be empty.`);
76
+ }
77
+ config.commands[verb] = line;
78
+ }
79
+ }
80
+ return config;
81
+ }
82
+ function asMapping(value, name, keys, source) {
83
+ if (value == null) return {};
84
+ if (typeof value !== "object" || Array.isArray(value)) {
85
+ throw new SiteError(`${source}: \`${name}:\` must be a mapping.`);
86
+ }
87
+ const obj = value;
88
+ for (const key of Object.keys(obj)) {
89
+ if (!keys.includes(key)) {
90
+ throw new SiteError(
91
+ `${source}: \`${name}:\` has unknown key "${key}". Supported keys: ${keys.join(", ")}.`
92
+ );
93
+ }
94
+ }
95
+ return obj;
96
+ }
97
+ function asString(value, key, source) {
98
+ if (typeof value !== "string") {
99
+ throw new SiteError(`${source}: ${SECTION}.${key} must be a string.`);
100
+ }
101
+ return value;
102
+ }
103
+
104
+ // src/site/core/detect.ts
105
+ var has = (dir, ...parts) => existsSync(join(dir, ...parts));
106
+ var read = (path) => {
107
+ try {
108
+ return readFileSync(path, "utf8");
109
+ } catch {
110
+ return "";
111
+ }
112
+ };
113
+ var dep = (name) => (s) => s.deps.has(name) ? name : null;
114
+ var node = (bin, start, build, preview, args = []) => ({
115
+ start: { script: start, argv: [bin, "dev", ...args] },
116
+ build: { script: build, argv: [bin, "build", ...args] },
117
+ preview: { script: preview, argv: [bin, "preview", ...args] }
118
+ });
119
+ var next = () => ({
120
+ start: { script: "dev", argv: ["next", "dev"] },
121
+ build: { script: "build", argv: ["next", "build"] },
122
+ preview: { script: "start", argv: ["next", "start"] }
123
+ });
124
+ function mintlify(s) {
125
+ if (has(s.dir, "mint.json")) return "mint.json";
126
+ try {
127
+ const doc = JSON.parse(read(join(s.dir, "docs.json")));
128
+ const schema = doc.$schema;
129
+ const shaped = typeof doc.theme === "string" && typeof doc.navigation === "object" && doc.navigation !== null;
130
+ if (typeof schema === "string" && schema.includes("mintlify") || shaped) {
131
+ return "docs.json";
132
+ }
133
+ } catch {
134
+ }
135
+ return null;
136
+ }
137
+ var zensicalSeen = /* @__PURE__ */ new WeakMap();
138
+ function zensical(s) {
139
+ const seen = zensicalSeen.get(s);
140
+ if (seen !== void 0) return seen;
141
+ const found = zensicalMarker(s);
142
+ zensicalSeen.set(s, found);
143
+ return found;
144
+ }
145
+ function zensicalMarker(s) {
146
+ if (has(s.dir, "zensical.toml")) return "zensical.toml";
147
+ if (!has(s.dir, "mkdocs.yml")) return null;
148
+ let files;
149
+ try {
150
+ files = readdirSync(s.dir).filter((f) => /^requirements.*\.txt$/.test(f) || f === "pyproject.toml");
151
+ } catch {
152
+ return null;
153
+ }
154
+ return files.some((f) => /\bzensical\b/.test(read(join(s.dir, f)))) ? "mkdocs.yml" : null;
155
+ }
156
+ var sphinxSource = (s) => has(s.dir, "conf.py") ? "." : "source";
157
+ var FRAMEWORKS = [
158
+ {
159
+ name: "Mintlify",
160
+ marker: mintlify,
161
+ runner: "path",
162
+ commands: () => ({ start: { argv: ["mint", "dev"] } }),
163
+ hostFlag: null,
164
+ defaultPort: 3e3
165
+ },
166
+ {
167
+ name: "Fern",
168
+ marker: (s) => has(s.dir, "fern", "fern.config.json") ? "fern/fern.config.json" : null,
169
+ runner: "path",
170
+ commands: () => ({ start: { argv: ["fern", "docs", "dev"] } }),
171
+ hostFlag: null,
172
+ defaultPort: 3e3
173
+ },
174
+ {
175
+ name: "Starlight",
176
+ marker: dep("@astrojs/starlight"),
177
+ runner: "node",
178
+ pkg: () => "astro",
179
+ commands: () => node("astro", "dev", "build", "preview"),
180
+ hostFlag: "--host",
181
+ defaultPort: 4321
182
+ },
183
+ {
184
+ name: "Docusaurus",
185
+ marker: dep("@docusaurus/core"),
186
+ runner: "node",
187
+ pkg: () => "@docusaurus/core",
188
+ commands: () => ({
189
+ start: { script: "start", argv: ["docusaurus", "start"] },
190
+ build: { script: "build", argv: ["docusaurus", "build"] },
191
+ preview: { script: "serve", argv: ["docusaurus", "serve"] }
192
+ }),
193
+ hostFlag: "--host",
194
+ defaultPort: 3e3
195
+ },
196
+ {
197
+ name: "VitePress",
198
+ marker: dep("vitepress"),
199
+ runner: "node",
200
+ pkg: () => "vitepress",
201
+ commands: (s) => node("vitepress", "docs:dev", "docs:build", "docs:preview", has(s.dir, ".vitepress") || !has(s.dir, "docs", ".vitepress") ? [] : ["docs"]),
202
+ hostFlag: "--host",
203
+ defaultPort: 5173
204
+ },
205
+ {
206
+ name: "Nextra",
207
+ marker: dep("nextra"),
208
+ runner: "node",
209
+ pkg: () => "next",
210
+ commands: next,
211
+ hostFlag: "--hostname",
212
+ defaultPort: 3e3
213
+ },
214
+ {
215
+ name: "Fumadocs",
216
+ marker: dep("fumadocs-core"),
217
+ runner: "node",
218
+ pkg: () => "next",
219
+ commands: next,
220
+ hostFlag: "--hostname",
221
+ defaultPort: 3e3
222
+ },
223
+ {
224
+ name: "Rspress",
225
+ marker: (s) => dep("rspress")(s) ?? dep("@rspress/core")(s),
226
+ runner: "node",
227
+ pkg: (s) => s.deps.has("rspress") ? "rspress" : "@rspress/core",
228
+ commands: () => node("rspress", "dev", "build", "preview"),
229
+ hostFlag: "--host",
230
+ defaultPort: 3e3
231
+ },
232
+ {
233
+ name: "MkDocs",
234
+ marker: (s) => has(s.dir, "mkdocs.yml") && zensical(s) === null ? "mkdocs.yml" : null,
235
+ runner: "python",
236
+ commands: () => ({ start: { argv: ["mkdocs", "serve"] }, build: { argv: ["mkdocs", "build"] }, out: "site" }),
237
+ hostFlag: "-a",
238
+ defaultPort: 8e3
239
+ },
240
+ {
241
+ name: "Zensical",
242
+ marker: zensical,
243
+ runner: "python",
244
+ commands: () => ({ start: { argv: ["zensical", "serve"] }, build: { argv: ["zensical", "build"] }, out: "site" }),
245
+ hostFlag: "-a",
246
+ defaultPort: 8e3
247
+ },
248
+ {
249
+ name: "Sphinx",
250
+ marker: (s) => has(s.dir, "conf.py") ? "conf.py" : has(s.dir, "source", "conf.py") ? "source/conf.py" : null,
251
+ runner: "python",
252
+ commands: (s) => {
253
+ const src = sphinxSource(s);
254
+ return {
255
+ start: { argv: ["sphinx-autobuild", src, posix.join(src, "_build", "html")] },
256
+ build: { argv: ["sphinx-build", "-M", "html", src, posix.join(src, "_build")] },
257
+ out: posix.join(src, "_build", "html")
258
+ };
259
+ },
260
+ hostFlag: "--host",
261
+ defaultPort: 8e3
262
+ },
263
+ {
264
+ name: "Hugo",
265
+ marker: (s) => ["hugo.toml", "hugo.yaml", "hugo.json"].find((f) => has(s.dir, f)) ?? null,
266
+ runner: "path",
267
+ commands: () => ({ start: { argv: ["hugo", "server"] }, build: { argv: ["hugo"] }, out: "public" }),
268
+ hostFlag: "--bind",
269
+ defaultPort: 1313
270
+ },
271
+ {
272
+ name: "Jekyll",
273
+ marker: (s) => has(s.dir, "_config.yml") && /\b(jekyll|github-pages)\b/.test(read(join(s.dir, "Gemfile"))) ? "_config.yml" : null,
274
+ runner: "ruby",
275
+ commands: () => ({ start: { argv: ["jekyll", "serve"] }, build: { argv: ["jekyll", "build"] }, out: "_site" }),
276
+ hostFlag: "--host",
277
+ defaultPort: 4e3
278
+ }
279
+ ];
280
+ var LOCAL_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
281
+ var STATIC_HOST = "127.0.0.1";
282
+ var CONFIG_NAME = FAMILY_CONFIG_NAMES[0] ?? "manni.config.yaml";
283
+ var LOCKFILES = [
284
+ ["package-lock.json", "npm"],
285
+ ["npm-shrinkwrap.json", "npm"],
286
+ ["pnpm-lock.yaml", "pnpm"],
287
+ ["yarn.lock", "yarn"],
288
+ ["bun.lock", "bun"],
289
+ ["bun.lockb", "bun"]
290
+ ];
291
+ var EXEC = {
292
+ npm: ["npx"],
293
+ pnpm: ["pnpm", "exec"],
294
+ yarn: ["yarn"],
295
+ bun: ["bun", "x"]
296
+ };
297
+ function readPackageJson(dir) {
298
+ const text = read(join(dir, "package.json"));
299
+ if (text === "") return null;
300
+ try {
301
+ const value = JSON.parse(text);
302
+ return typeof value === "object" && value !== null ? value : null;
303
+ } catch {
304
+ return null;
305
+ }
306
+ }
307
+ var record = (value) => typeof value === "object" && value !== null ? value : {};
308
+ function siteAt(dir) {
309
+ const pkg = readPackageJson(dir);
310
+ return {
311
+ dir,
312
+ scripts: record(pkg?.scripts),
313
+ deps: /* @__PURE__ */ new Set([...Object.keys(record(pkg?.dependencies)), ...Object.keys(record(pkg?.devDependencies))])
314
+ };
315
+ }
316
+ function packageManager(dir) {
317
+ const chain = searchPath(dir);
318
+ for (const d of chain) {
319
+ const field = readPackageJson(d)?.packageManager;
320
+ const name = typeof field === "string" ? field.split("@")[0] : void 0;
321
+ if (name !== void 0 && Object.hasOwn(EXEC, name)) return name;
322
+ }
323
+ for (const d of chain) {
324
+ const hit = LOCKFILES.find(([file]) => has(d, file));
325
+ if (hit) return hit[1];
326
+ }
327
+ return "npm";
328
+ }
329
+ function pythonPrefix(dir) {
330
+ for (const d of searchPath(dir)) {
331
+ if (has(d, "uv.lock")) return ["uv", "run"];
332
+ if (has(d, "poetry.lock")) return ["poetry", "run"];
333
+ }
334
+ return [];
335
+ }
336
+ function isDirectory(path) {
337
+ try {
338
+ return statSync(path).isDirectory();
339
+ } catch {
340
+ return false;
341
+ }
342
+ }
343
+ function parsePort(raw) {
344
+ const port = /^\d+$/.test(raw) ? Number(raw) : NaN;
345
+ if (!(port >= 1 && port <= 65535)) {
346
+ throw new SiteError(`--port must be an integer from 1 to 65535, got "${raw}".`);
347
+ }
348
+ return port;
349
+ }
350
+ function shellQuote(arg) {
351
+ if (/^[\w@%+=:,./-]+$/.test(arg)) return arg;
352
+ return process.platform === "win32" ? `"${arg.replace(/"/g, '""')}"` : `'${arg.replace(/'/g, "'\\''")}'`;
353
+ }
354
+ var andList = (items) => items.length <= 1 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items.at(-1) ?? ""}`;
355
+ function collectionAddress(collections, framework, portFlag) {
356
+ const local = collections.flatMap((c) => {
357
+ if (c.url === void 0) return [];
358
+ const url = new URL(c.url);
359
+ if (!LOCAL_HOSTS.has(url.hostname)) return [];
360
+ const port = url.port === "" ? url.protocol === "https:" ? 443 : 80 : Number(url.port);
361
+ return [{ name: c.name, host: url.hostname.replace(/^\[|\]$/g, ""), port, base: url.pathname }];
362
+ });
363
+ const [first] = local;
364
+ if (first === void 0) return { base: "/" };
365
+ if (local.some((l) => l.host !== first.host || l.port !== first.port)) {
366
+ if (!portFlag) {
367
+ warn(
368
+ `collections ${andList(local.map((l) => l.name))} name different local URLs. Using ${framework}'s default port; pass --port to pick one.`
369
+ );
370
+ }
371
+ return { base: "/" };
372
+ }
373
+ return { ...first, base: sharedPath(local.map((l) => l.base)) };
374
+ }
375
+ function sharedPath(paths) {
376
+ const split = paths.map((p) => p.split("/").filter((s) => s !== ""));
377
+ const [head = [], ...rest] = split;
378
+ const shared = [];
379
+ for (const [i, segment] of head.entries()) {
380
+ if (!rest.every((p) => p[i] === segment)) break;
381
+ shared.push(segment);
382
+ }
383
+ return shared.length === 0 ? "/" : `/${shared.join("/")}/`;
384
+ }
385
+ function addressArgs(fw, host, port) {
386
+ if (fw.hostFlag === "-a") {
387
+ if (host === void 0 && port === void 0) return [];
388
+ const h = host ?? STATIC_HOST;
389
+ return ["-a", `${h.includes(":") ? `[${h}]` : h}:${String(port ?? fw.defaultPort)}`];
390
+ }
391
+ return [
392
+ ...host !== void 0 && fw.hostFlag !== null ? [fw.hostFlag, host] : [],
393
+ ...port !== void 0 ? ["--port", String(port)] : []
394
+ ];
395
+ }
396
+ function resolvePlan(verb, opts) {
397
+ const config = loadSiteConfig(opts.cwd, opts.configPath);
398
+ const shown = (dir) => {
399
+ const rel = relative(opts.cwd, dir).replace(/\\/g, "/");
400
+ return rel === "" ? "./" : `${rel}/`;
401
+ };
402
+ const serving = verb === "build" ? null : verb;
403
+ const flagPort = serving !== null && opts.port !== void 0 ? parsePort(opts.port) : void 0;
404
+ const flagHost = serving !== null ? opts.host : void 0;
405
+ if (serving !== null && config.commands[serving] !== void 0) {
406
+ if (flagPort !== void 0) {
407
+ throw new SiteError(`--port does not apply to site.commands.${serving}. Put the port in that command.`);
408
+ }
409
+ if (flagHost !== void 0) {
410
+ throw new SiteError(`--host does not apply to site.commands.${serving}. Put the host in that command.`);
411
+ }
412
+ }
413
+ const needed = verb === "preview" ? ["build", "preview"] : [verb];
414
+ const missing = needed.find((v) => config.commands[v] === void 0);
415
+ const key = `site.commands.${missing ?? verb} in ${CONFIG_NAME}`;
416
+ const setIt = `Set ${key}.`;
417
+ let site;
418
+ const explicit = opts.dir !== void 0 ? resolve2(opts.cwd, opts.dir) : config.dir;
419
+ if (explicit !== void 0) {
420
+ if (!isDirectory(explicit)) throw new SiteError(`${shown(explicit)} does not exist.`);
421
+ const dir = has(explicit, "fern.config.json") && !has(explicit, "fern", "fern.config.json") ? dirname(explicit) : explicit;
422
+ site = siteAt(dir);
423
+ } else {
424
+ const base = config.configDir ?? resolve2(opts.cwd);
425
+ const candidates = [base, join(base, "docs"), join(base, "website"), join(base, "site")];
426
+ for (const dir of candidates) {
427
+ if (!isDirectory(dir)) continue;
428
+ const candidate = siteAt(dir);
429
+ if (FRAMEWORKS.some((fw2) => fw2.marker(candidate) !== null)) {
430
+ site = candidate;
431
+ break;
432
+ }
433
+ }
434
+ if (site === void 0) {
435
+ if (missing !== void 0) {
436
+ const names = candidates.map(shown);
437
+ throw new SiteError(
438
+ `no docs site found in ${names.slice(0, -1).join(", ")} or ${names.at(-1) ?? ""}. Pass the site's directory, or set ${key}.`
439
+ );
440
+ }
441
+ site = siteAt(base);
442
+ }
443
+ }
444
+ const where = shown(site.dir);
445
+ const found = site;
446
+ const matches = FRAMEWORKS.flatMap((fw2) => {
447
+ const marker = fw2.marker(found);
448
+ return marker === null ? [] : [{ fw: fw2, marker }];
449
+ });
450
+ let fw;
451
+ if (missing !== void 0) {
452
+ if (matches.length === 0) throw new SiteError(`no docs framework detected in ${where}. ${setIt}`);
453
+ if (matches.length > 1) {
454
+ const list = matches.map((m) => `${m.fw.name} (${m.marker})`).join(", ");
455
+ throw new SiteError(`${where} holds more than one docs site: ${list}. ${setIt}`);
456
+ }
457
+ fw = matches[0]?.fw;
458
+ }
459
+ const steps = needed.map((v) => {
460
+ const override = config.commands[v];
461
+ const isServe = v === serving;
462
+ const extra = v === verb ? opts.passthrough : [];
463
+ if (override !== void 0) {
464
+ const command = [override, ...extra.map(shellQuote)].join(" ");
465
+ return {
466
+ announce: `Running site.commands.${v} in ${where}: ${command}`,
467
+ display: command,
468
+ notFound: "",
469
+ step: { kind: "shell", command, cwd: found.dir }
470
+ };
471
+ }
472
+ if (fw === void 0) throw new SiteError(`no docs framework detected in ${where}. ${setIt}`);
473
+ const cmds = fw.commands(found);
474
+ const cmd = cmds[v];
475
+ if (v === "build" && cmd === void 0) {
476
+ throw new SiteError(`${fw.name} has no local build. Run manni site start, or set site.commands.build.`);
477
+ }
478
+ let address = { base: "/" };
479
+ if (isServe) {
480
+ if (flagHost !== void 0 && fw.hostFlag === null) {
481
+ throw new SiteError(`${fw.name}'s dev server takes no host option. Drop --host.`);
482
+ }
483
+ const url = collectionAddress(config.collections, fw.name, flagPort !== void 0);
484
+ address = { host: flagHost ?? url.host, port: flagPort ?? url.port, base: url.base };
485
+ }
486
+ if (cmd === void 0) {
487
+ if (cmds.out === void 0) {
488
+ throw new SiteError(`${fw.name} has no local preview. Run manni site start, or set site.commands.preview.`);
489
+ }
490
+ if (extra.length > 0) {
491
+ throw new SiteError(`${fw.name} previews through manni's built-in server, which takes no extra arguments. Drop the arguments after --.`);
492
+ }
493
+ return {
494
+ announce: "",
495
+ display: "",
496
+ notFound: "",
497
+ step: {
498
+ kind: "static",
499
+ root: join(found.dir, cmds.out),
500
+ host: address.host ?? STATIC_HOST,
501
+ port: address.port ?? fw.defaultPort,
502
+ base: address.base
503
+ }
504
+ };
505
+ }
506
+ const flags = [...isServe ? addressArgs(fw, address.host, address.port) : [], ...extra];
507
+ let argv;
508
+ if (fw.runner === "node") {
509
+ const pm = packageManager(found.dir);
510
+ requireInstalled(fw, found, pm, where);
511
+ argv = cmd.script !== void 0 && cmd.script in found.scripts ? [pm, "run", cmd.script, ...pm === "npm" && flags.length > 0 ? ["--"] : [], ...flags] : [...EXEC[pm], ...cmd.argv, ...flags];
512
+ } else {
513
+ const prefix = fw.runner === "python" ? pythonPrefix(found.dir) : fw.runner === "ruby" ? ["bundle", "exec"] : [];
514
+ argv = [...prefix, ...cmd.argv, ...flags];
515
+ }
516
+ const display = argv.join(" ");
517
+ const bin = argv[0] ?? "";
518
+ const install = bin === cmd.argv[0] ? `${fw.name}'s CLI` : bin;
519
+ return {
520
+ announce: `${fw.name} in ${where}. Running ${display}`,
521
+ display,
522
+ notFound: `${bin} not found on PATH. Install ${install}, or set site.commands.${v}.`,
523
+ step: { kind: "exec", argv, cwd: found.dir }
524
+ };
525
+ });
526
+ return { steps };
527
+ }
528
+ function requireInstalled(fw, site, pm, where) {
529
+ const pkg = fw.pkg?.(site);
530
+ if (pkg === void 0) return;
531
+ const chain = searchPath(site.dir);
532
+ if (chain.some((d) => has(d, "node_modules", pkg, "package.json"))) return;
533
+ if (chain.some((d) => has(d, ".pnp.cjs") || has(d, ".pnp.js"))) return;
534
+ const npmLock = chain.some((d) => has(d, "package-lock.json") || has(d, "npm-shrinkwrap.json"));
535
+ const install = pm === "npm" ? npmLock ? "npm ci" : "npm install" : `${pm} install`;
536
+ throw new SiteError(`${pkg} is not installed for ${where}. Run ${install} in ${where} first.`);
537
+ }
538
+
539
+ // src/site/core/run.ts
540
+ import { spawn } from "node:child_process";
541
+ import { accessSync, constants, statSync as statSync2 } from "node:fs";
542
+ import { delimiter, resolve as resolve4 } from "node:path";
543
+
544
+ // src/site/core/static-server.ts
545
+ import { createReadStream } from "node:fs";
546
+ import { stat } from "node:fs/promises";
547
+ import { createServer } from "node:http";
548
+ import { extname, join as join2, relative as relative2, resolve as resolve3, sep } from "node:path";
549
+ var MIME = {
550
+ ".html": "text/html; charset=utf-8",
551
+ ".css": "text/css; charset=utf-8",
552
+ ".js": "text/javascript; charset=utf-8",
553
+ ".mjs": "text/javascript; charset=utf-8",
554
+ ".json": "application/json; charset=utf-8",
555
+ ".map": "application/json; charset=utf-8",
556
+ ".txt": "text/plain; charset=utf-8",
557
+ ".xml": "application/xml; charset=utf-8",
558
+ ".svg": "image/svg+xml",
559
+ ".png": "image/png",
560
+ ".jpg": "image/jpeg",
561
+ ".jpeg": "image/jpeg",
562
+ ".gif": "image/gif",
563
+ ".webp": "image/webp",
564
+ ".avif": "image/avif",
565
+ ".ico": "image/x-icon",
566
+ ".woff": "font/woff",
567
+ ".woff2": "font/woff2",
568
+ ".ttf": "font/ttf",
569
+ ".wasm": "application/wasm",
570
+ ".pdf": "application/pdf",
571
+ ".webmanifest": "application/manifest+json"
572
+ };
573
+ function normalizeBase(base) {
574
+ const trimmed = base.replace(/^\/+|\/+$/g, "");
575
+ return trimmed === "" ? "/" : `/${trimmed}/`;
576
+ }
577
+ async function kindOf(path) {
578
+ try {
579
+ const s = await stat(path);
580
+ if (s.isDirectory()) return "dir";
581
+ return s.isFile() ? "file" : void 0;
582
+ } catch {
583
+ return void 0;
584
+ }
585
+ }
586
+ function sendFile(req, res, path, status = 200) {
587
+ res.writeHead(status, {
588
+ "content-type": MIME[extname(path).toLowerCase()] ?? "application/octet-stream"
589
+ });
590
+ if (req.method === "HEAD") {
591
+ res.end();
592
+ return;
593
+ }
594
+ createReadStream(path).on("error", () => res.destroy()).pipe(res);
595
+ }
596
+ function redirect(res, status, location) {
597
+ res.writeHead(status, { location });
598
+ res.end();
599
+ }
600
+ function inside(root, rest) {
601
+ let decoded;
602
+ try {
603
+ decoded = decodeURIComponent(rest);
604
+ } catch {
605
+ return void 0;
606
+ }
607
+ if (decoded.includes("\0") || decoded.split(/[\\/]/).includes("..")) return void 0;
608
+ const path = resolve3(root, `.${sep}${decoded}`);
609
+ return path === root || path.startsWith(root + sep) ? path : void 0;
610
+ }
611
+ function handler(root, base) {
612
+ const notFound = join2(root, "404.html");
613
+ return async (req, res) => {
614
+ if (req.method !== "GET" && req.method !== "HEAD") {
615
+ res.writeHead(405, { allow: "GET, HEAD" });
616
+ res.end();
617
+ return;
618
+ }
619
+ const url = new URL(req.url ?? "/", "http://localhost");
620
+ const { pathname } = url;
621
+ if (base !== "/" && (pathname === "/" || pathname === base.slice(0, -1))) {
622
+ redirect(res, pathname === "/" ? 302 : 301, `${base}${url.search}`);
623
+ return;
624
+ }
625
+ const path = pathname.startsWith(base) ? inside(root, pathname.slice(base.length)) : void 0;
626
+ const kind = path === void 0 ? void 0 : await kindOf(path);
627
+ if (path !== void 0 && kind === "dir" && !pathname.endsWith("/")) {
628
+ redirect(res, 301, `${pathname}/${url.search}`);
629
+ return;
630
+ }
631
+ const file = path !== void 0 && kind === "dir" ? join2(path, "index.html") : path;
632
+ if (file !== void 0 && await kindOf(file) === "file") {
633
+ sendFile(req, res, file);
634
+ } else if (await kindOf(notFound) === "file") {
635
+ sendFile(req, res, notFound, 404);
636
+ } else {
637
+ res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
638
+ res.end("Not found\n");
639
+ }
640
+ };
641
+ }
642
+ function urlOf(host, port, base) {
643
+ const shown = host.includes(":") ? `[${host}]` : host;
644
+ return `http://${shown}:${String(port)}${base}`;
645
+ }
646
+ async function startStaticServer(opts) {
647
+ const root = resolve3(opts.root);
648
+ if (await kindOf(root) !== "dir") {
649
+ const shown = relative2(process.cwd(), root).split(sep).join("/") || ".";
650
+ throw new SiteError(`${shown}/ does not exist.`);
651
+ }
652
+ const base = normalizeBase(opts.base);
653
+ const handle = handler(root, base);
654
+ const server = createServer((req, res) => {
655
+ handle(req, res).catch(() => res.destroy());
656
+ });
657
+ await new Promise((settle, reject) => {
658
+ server.once("error", (err) => {
659
+ reject(
660
+ new SiteError(
661
+ err.code === "EADDRINUSE" ? `port ${String(opts.port)} is in use. Pass --port, or stop the process holding it.` : `cannot listen on ${urlOf(opts.host, opts.port, "")}: ${errorMessage(err)}`
662
+ )
663
+ );
664
+ });
665
+ server.listen(opts.port, opts.host, settle);
666
+ });
667
+ const { port } = server.address();
668
+ process.stdout.write(`${urlOf(opts.host, port, base)}
669
+ `);
670
+ return server;
671
+ }
672
+ async function serveStatic(opts) {
673
+ const server = await startStaticServer(opts);
674
+ await new Promise((settle) => {
675
+ const stop = () => {
676
+ process.off("SIGINT", stop);
677
+ process.off("SIGTERM", stop);
678
+ server.close(() => {
679
+ settle();
680
+ });
681
+ server.closeAllConnections();
682
+ };
683
+ process.on("SIGINT", stop);
684
+ process.on("SIGTERM", stop);
685
+ });
686
+ }
687
+
688
+ // src/site/core/run.ts
689
+ function isExecutable(path) {
690
+ try {
691
+ if (!statSync2(path).isFile()) return false;
692
+ if (process.platform !== "win32") accessSync(path, constants.X_OK);
693
+ return true;
694
+ } catch {
695
+ return false;
696
+ }
697
+ }
698
+ function findOnPath(name, cwd) {
699
+ const win = process.platform === "win32";
700
+ const exts = win ? (process.env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD").split(";").filter((e) => e !== "") : [];
701
+ const lower = name.toLowerCase();
702
+ const names = win && !exts.some((e) => lower.endsWith(e.toLowerCase())) ? exts.map((e) => name + e) : [name];
703
+ const dirs = /[\\/]/.test(name) ? [cwd] : (process.env["PATH"] ?? "").split(delimiter).filter((d) => d !== "");
704
+ for (const dir of dirs) {
705
+ for (const candidate of names) {
706
+ const path = resolve4(dir, candidate);
707
+ if (isExecutable(path)) return path;
708
+ }
709
+ }
710
+ return void 0;
711
+ }
712
+ function startExec(planned, step) {
713
+ const [name, ...args] = step.argv;
714
+ const binary = name === void 0 ? void 0 : findOnPath(name, step.cwd);
715
+ if (binary === void 0) throw new SiteError(planned.notFound);
716
+ const line = launcherCommandLine(
717
+ binary,
718
+ args,
719
+ (value) => new SiteError(`${planned.display} cannot be given an argument containing a quote: ${value}`)
720
+ );
721
+ return spawn(line.command, line.argv, {
722
+ cwd: step.cwd,
723
+ stdio: "inherit",
724
+ windowsVerbatimArguments: line.verbatim
725
+ });
726
+ }
727
+ function exitOf(planned, child) {
728
+ return new Promise((settle, reject) => {
729
+ child.once("error", (err) => {
730
+ reject(
731
+ err.code === "ENOENT" ? new SiteError(planned.notFound) : new SiteError(`${planned.display} could not start: ${err.message}`)
732
+ );
733
+ });
734
+ child.once("exit", (code, signal) => {
735
+ settle({ code, signal });
736
+ });
737
+ });
738
+ }
739
+ async function runStep(planned) {
740
+ const { step } = planned;
741
+ if (step.kind === "static") {
742
+ await serveStatic(step);
743
+ return true;
744
+ }
745
+ const child = step.kind === "exec" ? startExec(planned, step) : spawn(step.command, { cwd: step.cwd, stdio: "inherit", shell: true });
746
+ const signal = { received: false };
747
+ const onInt = () => {
748
+ signal.received = true;
749
+ };
750
+ const onTerm = () => {
751
+ signal.received = true;
752
+ child.kill("SIGTERM");
753
+ };
754
+ process.on("SIGINT", onInt);
755
+ process.on("SIGTERM", onTerm);
756
+ try {
757
+ const exit = await exitOf(planned, child);
758
+ if (signal.received) return true;
759
+ if (exit.code === 0) return false;
760
+ throw new SiteError(
761
+ exit.code === null ? `${planned.display} was stopped by ${String(exit.signal)}.` : `${planned.display} exited with code ${String(exit.code)}.`
762
+ );
763
+ } finally {
764
+ process.off("SIGINT", onInt);
765
+ process.off("SIGTERM", onTerm);
766
+ }
767
+ }
768
+ async function runPlan(plan) {
769
+ for (const planned of plan.steps) {
770
+ if (planned.announce !== "") notice(planned.announce);
771
+ if (await runStep(planned)) break;
772
+ }
773
+ return 0;
774
+ }
775
+
776
+ // src/site/commands/run.ts
777
+ async function runSite(verb, opts) {
778
+ return runPlan(resolvePlan(verb, opts));
779
+ }
780
+
781
+ // src/site/cli.ts
782
+ function splitOperands(args) {
783
+ const at = process.argv.indexOf("--");
784
+ const tail = at === -1 ? [] : process.argv.slice(at + 1);
785
+ const start = args.length - tail.length;
786
+ const passthrough = start >= 0 && tail.every((arg, i) => args[start + i] === arg) ? tail : [];
787
+ const before = args.slice(0, args.length - passthrough.length);
788
+ return { dir: before[0], passthrough, extra: before.length };
789
+ }
790
+ function buildProgram() {
791
+ const program = new Command();
792
+ program.name("site").description("Start, build and preview the docs site").version(package_default.version, "-V, --version").showHelpAfterError("(add --help for usage)").exitOverride();
793
+ const verb = (name, description, serves) => {
794
+ const cmd = program.command(name).description(description).argument("[dir]", "the site's directory (default: site.dir, else found by search)").allowExcessArguments();
795
+ if (serves) {
796
+ cmd.option("--port <n>", "port, an integer from 1 to 65535 (default: a local collection url, else the framework's)").option("--host <host>", "host to bind (default: a local collection url, else the framework's)");
797
+ }
798
+ cmd.option("-c, --config <file>", "path to a manni config file").action(async (_dir, options, self) => {
799
+ const { dir, passthrough, extra } = splitOperands(self.args);
800
+ if (extra > 1) {
801
+ self.error(
802
+ `error: too many arguments for '${name}'. Expected 1 argument but got ${String(extra)}.`,
803
+ { code: "commander.excessArguments" }
804
+ );
805
+ }
806
+ try {
807
+ process.exitCode = await runSite(name, {
808
+ cwd: process.cwd(),
809
+ dir,
810
+ configPath: options.config,
811
+ port: options.port,
812
+ host: options.host,
813
+ passthrough
814
+ });
815
+ } catch (err) {
816
+ fail(err);
817
+ }
818
+ });
819
+ };
820
+ verb("start", "Run the docs framework's dev server", true);
821
+ verb("build", "Build the docs site", false);
822
+ verb("preview", "Build the docs site, then serve the output", true);
823
+ program.addHelpText(
824
+ "after",
825
+ [
826
+ "",
827
+ "Examples:",
828
+ " manni site start # detect the framework, run its dev server",
829
+ " manni site build",
830
+ " manni site preview --port 4000 # build, then serve the output",
831
+ " manni site start website -- --open # arguments after -- go to the framework"
832
+ ].join("\n")
833
+ );
834
+ return program;
835
+ }
836
+ export {
837
+ buildProgram
838
+ };
839
+ //# sourceMappingURL=cli-LWST5FQH.js.map